cassemblygcc

why gcc generates "leal -8240(%ebp), %eax; cmpl $1, %eax; ja XXX" instead of jmp instruction?


I am studying the assembly code generated by the gcc. However, I found the following code fragment:

.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

By investigating the soure code, I discover that this should be a jmp instruction. Why gcc compiler use 3 instructions instead of 1 instruction? Is it more efficient or it is portable among the X86 cpu(I do not know any x86 cpu not supporting the jmp instruction)

MY REASON: The next instruction of ja is a mov instruction at .LBB77 and this mov instruction corresponding to the source at line 373. If ja does not jump, then this is a cross-function execution . This is a very bizarre behaviour and is not expected. Therefore I concluded it must be a "jmp".

FINAL RESULTS: This is NOT a jmp. It may run the instructions of line 373 in the source. CLOSED.

============================ more information:

 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 

Solution

  • At first glance, this small piece of code seems to be grabbing the address of something on the stack -- the address of a local variable -- putting it in a register, seeing if it is greater than 1, and executing the jump only if it is.

    But I am not quite sure why gcc would want to compare the address to the literal 1, because nearly every address is greater than 1, in which case jmp would probably work just as well as ja. So perhaps it is using the ebp register to hold something other than the address of the stack?

    In any case, it is not strictly a simple jump.