Skip to content

Instantly share code, notes, and snippets.

@udiboy1209
Created January 25, 2018 23:38
Show Gist options
  • Save udiboy1209/12293f2294285947e67f174f3ccaad33 to your computer and use it in GitHub Desktop.
Save udiboy1209/12293f2294285947e67f174f3ccaad33 to your computer and use it in GitHub Desktop.

ASM basics

  • %r** and %e** are registers. Registers store output of instructions and can be used to give input to instructions
  • when writing (%r**), it is accessing memory location given by value of register %r**. Its like pointer dereferencing. A number before a memory access applies an offset to the accessed location. -8(%rdi) would get value at memory location given by %rdi-8.
  • %rdi register is used internally to pass reference of class instance to a member function of that class.
  • %rbp register stores the location of start of stack frame of that function. That is why all temp values will be stored relative to it. Stacks grow downward (towards 0) hence you see so many negative offsets.
  • movl %rs,%rd and movq %rs,%rd move 32 bit and 64 bit values from %rs (source register) to %rd (destination register). A dereferenced register notation moves data to and from memory location.
  • leaq is a weird instruction to explain, it basically stores the address of memory access in 64-bit format. leaq -64(%rbp), %rax stores %rbp-64 in %rax without accessing that memory location.
_ZN3bar4scooEv:
pushq %rbp
movq %rsp, %rbp
pushq %r12
pushq %rbx
subq $80, %rsp
movq %rdi, -72(%rbp) # pointer to bar instance was passed in %rdi
movq %fs:40, %rax
movq %rax, -24(%rbp)
xorl %eax, %eax
# doo.gz()
# %rbp -> frame start
# %rbp-72 -> pointer to bar::doo (doo is at 0 offset)
# pass pointer to class instance in %rdi and call class member
movq -72(%rbp), %rax
movq %rax, %rdi
call _ZN3foo2gzEv # uses (%rdi+8) to return z value
movl %eax, %r12d
# doo.gy()
movq -72(%rbp), %rax
movq %rax, %rdi
call _ZN3foo2gyEv
movl %eax, %ebx
# doo.gx()
movq -72(%rbp), %rax
movq %rax, %rdi
call _ZN3foo2gxEv
movl %eax, %esi
# foo(int, int, int)
# args are passed in %ecx,%edx,%esi
# %rdi points to new foo instance at %rbp-64
leaq -64(%rbp), %rax
movl %r12d, %ecx
movl %ebx, %edx
movq %rax, %rdi
call _ZN3fooC1Eiii # constructor call
# new instance constructed at %rbp-64
# move it to %rbp-48
movq -64(%rbp), %rax
movq %rax, -48(%rbp)
movl -56(%rbp), %eax
movl %eax, -40(%rbp)
movq -48(%rbp), %rdx
movl -40(%rbp), %eax
# Store return value in %edx,%rax
movq %rdx, %rcx
movl %eax, %edx
movq %rcx, %rax
addq $80, %rsp
popq %rbx
popq %r12
popq %rbp
ret
_ZN3bar4scooEv:
pushq %rbp
movq %rsp, %rbp
pushq %r12
pushq %rbx
subq $80, %rsp
movq %rdi, -72(%rbp) # pointer to bar instance was passed in %rdi
movq %fs:40, %rax
movq %rax, -24(%rbp)
xorl %eax, %eax
# doo.gz()
# compare with scoo.asm
# This implementation takes address of %rbp-64, new empty doo object
# which is in scope of scoo
leaq -64(%rbp), %rax
movq %rax, %rdi
call _ZN3foo2gzEv
movl %eax, %r12d
# because foo instance at %rbp-64 isnt properly constructed
# function returns garbage. Same with rest two
# doo.gy()
leaq -64(%rbp), %rax
movq %rax, %rdi
call _ZN3foo2gyEv
movl %eax, %ebx
# doo.gx()
leaq -64(%rbp), %rax
movq %rax, %rdi
call _ZN3foo2gxEv
movl %eax, %esi
# foo(int,int,int)
# args are passed in %ecx,%edx,%esi (garbage values)
# %rdi points to new foo instance at %rbp-64
leaq -64(%rbp), %rax
movl %r12d, %ecx
movl %ebx, %edx
movq %rax, %rdi
call _ZN3fooC1Eiii
movq -64(%rbp), %rax
movq %rax, -48(%rbp)
movl -56(%rbp), %eax
movl %eax, -40(%rbp)
movq -48(%rbp), %rdx
movl -40(%rbp), %eax
movq %rdx, %rcx
movl %eax, %edx
movq %rcx, %rax
addq $80, %rsp
popq %rbx
popq %r12
popq %rbp
ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment