Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么gcc会产生“;leal -8240%(ebp),%eax;cmpl和#x9$1%eax;ja XXX“;而不是jmp指令?_C_Gcc_Assembly_Compiler Construction - Fatal编程技术网

为什么gcc会产生“;leal -8240%(ebp),%eax;cmpl和#x9$1%eax;ja XXX“;而不是jmp指令?

为什么gcc会产生“;leal -8240%(ebp),%eax;cmpl和#x9$1%eax;ja XXX“;而不是jmp指令?,c,gcc,assembly,compiler-construction,C,Gcc,Assembly,Compiler Construction,我正在研究gcc生成的汇编代码。 但是,我发现了以下代码片段: .LBE58: .loc 1 178 0 cmpl $8224, %ebp jl .L12 cmpl $8225, %ebp jle .L19 leal -8240(%ebp), %eax cmpl $1, %eax ja .L12 .LVL50: .LBB76: .LBB77: .loc 1 373 0 movl 60(%esi), %eax .loc 1 374 0 cmpl $8240,

我正在研究gcc生成的汇编代码。 但是,我发现了以下代码片段:

.LBE58:
.loc 1 178 0
cmpl    $8224, %ebp
jl  .L12
cmpl    $8225, %ebp
jle .L19
leal    -8240(%ebp), %eax
cmpl    $1, %eax
ja  .L12
.LVL50:
.LBB76:
.LBB77:
.loc 1 373 0
movl    60(%esi), %eax
.loc 1 374 0
cmpl    $8240, %ebp
.loc 1 373 0
movl    4(%eax), %ebx
通过研究源代码,我发现这应该是一条jmp指令。 为什么gcc编译器使用3条指令而不是1条指令? 它是更高效还是在x86CPU之间可移植(我不知道有哪个x86CPU不支持jmp指令)

我的理由: ja的下一条指令是位于.LBB77的mov指令,该mov指令对应于第373行的源。 如果ja没有跳转,那么这是一个跨函数执行。 这是一种非常奇怪的行为,是不可预料的。 因此,我断定它一定是一个“jmp”

最终结果: 这不是jmp。它可以在源代码中运行第373行的指令。 关闭。

========================================更多信息:

 178                 switch (s->state)
 179                         {
 180                 case SSL_ST_BEFORE:
 181                 case SSL_ST_ACCEPT:
 182                 case SSL_ST_BEFORE|SSL_ST_ACCEPT:
 183                 case SSL_ST_OK|SSL_ST_ACCEPT:

..................


 342                 default:
 343                         SSLerr(SSL_F_SSL2_ACCEPT,SSL_R_UNKNOWN_STATE);
 344                         ret= -1;
 345                         goto end;
 346                         /* BREAK; */
 347                         }
 348 
 349                 if ((cb != NULL) && (s->state != state))
 350                         {
 351                         new_state=s->state;
 352                         s->state=state;
 353                         cb(s,SSL_CB_ACCEPT_LOOP,1);
 354                         s->state=new_state;
 355                         }
 356                 }
 357 end:
 358         s->in_handshake--;
 359         if (cb != NULL)
 360                 cb(s,SSL_CB_ACCEPT_EXIT,ret);
 361         return(ret);
 362         }
 363
 364 static int get_client_master_key(SSL *s)
 365         {
 366         int is_export,i,n,keya,ek;
 367         unsigned long len;
 368         unsigned char *p;
 369         const SSL_CIPHER *cp;
 370         const EVP_CIPHER *c;
 371         const EVP_MD *md;
 372 
 373         p=(unsigned char *)s->init_buf->data;
 374         if (s->state == SSL2_ST_GET_CLIENT_MASTER_KEY_A)
 375                 {
 376                 i=ssl2_read(s,(char *)&(p[s->init_num]),10-s->init_num);
 377 
 378                 if (i < (10-s->init_num))
 379                         return(ssl2_part_read(s,SSL_F_GET_CLIENT_MASTER_KEY,i));
 380                 s->init_num = 10;
 381 
178开关->状态
179                         {
180箱SSL____之前:
181情况SSL_ST___接受:
182在接受SSL之前的情况:
183情况SSL_ST_OK | SSL_ST_接受:
..................
342默认值:
343 SSLerr(SSL\u F\u SSL2\u接受,SSL\u R\u未知状态);
344 ret=-1;
345转完;
346/*中断*/
347                         }
348
349如果((cb!=NULL)&&(s->state!=state))
350                         {
351新的_状态=s->state;
352秒->状态=状态;
353 cb(s,SSL_cb_接受_循环,1);
354 s->state=新状态;
355                         }
356                 }
357完:
358秒->in_握手--;
359如果(cb!=NULL)
360 cb(s、SSL、cb、接受、退出、ret);
361个返回(ret);
362         }
363
364静态整数获取客户端主密钥(SSL*s)
365         {
366 int是出口,i,n,keya,ek;
367个无符号长透镜;
368个无符号字符*p;
369 const SSL_CIPHER*cp;
370 const EVP_CIPHER*c;
371名施工执行副总裁(MD*MD);
372
373 p=(无符号字符*)s->init_buf->data;
374如果(s->state==SSL2\u ST\u GET\u CLIENT\u MASTER\u KEY\u A)
375                 {
376 i=ssl2读取(字符*)和(p[s->init_num]),10-s->init_num;
377
378如果(i<(10-s->init_num))
379返回(ssl2部分读取(s,SSL获取客户机主密钥,i));
380秒->初始数量=10;
381

乍一看,这一小段代码似乎在获取堆栈上某个对象的地址——局部变量的地址——将其放入寄存器,查看其是否大于1,并仅在大于1时执行跳转

但我不太清楚gcc为什么要将地址与文本
1
进行比较,因为几乎每个地址都大于1,在这种情况下
jmp
可能与
ja
一样工作。因此,它可能使用
ebp
寄存器来保存堆栈地址以外的内容


在任何情况下,这都不是一个简单的跳转。

对应的源代码是什么?编译器可能比您更了解如何编译;-)“通过调查源代码,我发现这应该是一条
jmp
指令。”你能详细说明一下你的调查吗?这三行构成了一个条件跳转,你认为编译器应该生成一个无条件跳转的理由是什么?没有一种更有效的方法将基指针偏移量的起始地址加载到寄存器中并进行比较。你关心什么?很好,那么现在你在谈论哪三条汇编语句?哪一行代码!你能在这里做些努力吗?这个问题很清楚。你还没有回答我的第二个问题。但是,这是一个“JMP”指令。一个原因是编译器确信它将始终跳转。switch语句很难处理。你是对的。我没有真正回答你的问题,这就是为什么他们会使用与简单跳转结果相同但占用更多空间和时间的东西。一种可能是ebp中存在某种东西它不是一个普通地址,而是一个偏移量,
lea
被用来做算术运算。在这种情况下,跳转可能会失败。是的。
ebp
不是地址,而是一个普通值。有一条指令:
cmpl$8289,%ebp