0

I have a simple C program that I assume generate simple assembly code

this is my C program

char *a="ba";
char x;

void main(){x=a[0];}

There is nothing especial about the generated assembly except

these lines

# test.c:4: void main(){x=a[0];}
    movq    a(%rip), %rax   # a, a.0_1
    movzbl  (%rax), %eax    # *a.0_1, _2
# test.c:4: void main(){x=a[0];}
    movb    %al, x(%rip)    # _2, x

so I am in the middle of my program assembly and all the sudden quad word worth of address is moved happens to be from rax to rip, so rip is instruction pointer so I like to know what is inside rax at following line

    movq    a(%rip), %rax   # a, a.0_1

does it hold my a[0], if it does that this makes sense because this line test.c:4: void main(){x=a[0];} movb %al, x(%rip) # _2, x so this mean my rax hold every element inside char *a and least significant type will be a[0] but I dont understood how come rax start holding my char *a I did not assign it then who assigned my char *a to rax register so I am assuming al there will be a[0] and a[1] will be at 8th to 15th byte of rax register. And what about this line movzbl (%rax), %eax # *a.0_1, _2 whats doing here

this is almost full assembly with disassembler directives

    .text
    .globl  a
    .section    .rodata
.LC0:
    .string "ba"
    .section    .data.rel.local,"aw"
    .align 8
    .type   a, @object
    .size   a, 8
a:
    .quad   .LC0
    .globl  x
    .bss
    .type   x, @object
    .size   x, 1
x:
    .zero   1
    .text
    .globl  main
    .type   main, @function
main:
    pushq   %rbp    #
    movq    %rsp, %rbp  #,

# test.c:4: void main(){x=a[0];}
    movq    a(%rip), %rax   # a, a.0_1
    movzbl  (%rax), %eax    # *a.0_1, _2
# test.c:4: void main(){x=a[0];}
    movb    %al, x(%rip)    # _2, x
# test.c:4: void main(){x=a[0];}
    nop 
    popq    %rbp    #
    ret 
user786
  • 3,902
  • 4
  • 40
  • 72
  • 3
    *"happens to be from rax to rip"* - you're reading the operands backwards. Your assembly listing uses AT&T syntax, which is `source, destination`. – Greg Hewgill Feb 23 '22 at 08:17
  • @GregHewgill what about `movzbl (%rax), %eax moves a[0] into rax` is this correct according to u `movzbl (%rax), %eax` should move rax to eax. Can u explain please? – user786 Feb 23 '22 at 08:45

1 Answers1

2
 movq    a(%rip), %rax

moves the value of a, which is the address of the string, into rax.

 movzbl  (%rax), %eax

moves a[0] into rax. (This reads one byte.)

 movb    %al, x(%rip)

moves the value of a[0] into x.

The first and third of these instructions mention rip because they use rip-relative addressing, which is typical for accessing static variables in 64-bit code.

prl
  • 11,716
  • 2
  • 13
  • 31
  • `movq a(%rip),rax` so what is `(%rip)` why not it simply is `movq a,rax` ? I believe rax is destination – user786 Feb 23 '22 at 08:38
  • `movzbl (%rax), %eax moves a[0] into rax` u mean moves `a[0]` into eax. If we are using AT&T syntax I got the comment on that here – user786 Feb 23 '22 at 08:43
  • In 64-bit mode, `mov xxx, %eax` actually writes to rax. It clears the upper 32 bits. – prl Feb 23 '22 at 08:47
  • Can I omit (%rip) from the instruction will it work? – user786 Feb 23 '22 at 08:49
  • It will work if your code is linked below 2 GB and it is loaded where it is linked. If its virtual address is above 2 GB, or if it is loaded at a different address, then it won't work. – prl Feb 23 '22 at 09:04
  • 2GB is lots of memory do ppl normally omit this. Or it's big or even middle size no – user786 Feb 23 '22 at 09:15
  • 1
    In 64-bit code, everything should be RIP-relative. – prl Feb 23 '22 at 11:43