#[SOLVED] getting return address in assembly

1 messages · Page 1 of 1 (latest)

tribal warren
#

I'm trying to wrap my head around some assembly stuff, and I'm getting results that don't really make sense to me. Here's the program:

package main
import "base:runtime"
import "core:fmt"
foreign import asmb "./test.asm"

foreign asmb {
    asm_print_addr :: proc "c" () ---
}

main :: proc() {
    print_int(uint(uintptr(rawptr(main))))
    print_int(uint(uintptr(rawptr(foo))))
    asm_print_addr()
    asm_print_addr()

    foo()

    asm_print_addr()
    asm_print_addr()
}

foo :: proc() {
    fmt.println("foo start")
    asm_print_addr()
    asm_print_addr()
    fmt.println("foo end")
}

@export
print_int :: proc "c"(n: uint) {
    runtime.print_uint(n)
    runtime.print_byte('\n')
}
bits 64

global asm_print_addr
extern  print_int

section .text
asm_print_addr:
    lea  rcx, [rsp]
    call print_int
    ret

and here's the output

140696436048272
140696436048352
715696109176
715696109176
foo start
715696109048
715696109048
foo end
715696109176
715696109176

The exact addresses vary each time, which makes sense, but I'm confused how each invocation of asm_print_addr prints out the same return address, and I'm confused why those numbers are so different from the actual procedure pointers for main and foo

#

ah, figured it out

#

i wanted mov rcx, [rsp], not lea rcx, [rsp]

#

since i believe that lea effectively cancels out the brackets, which means deferencing, so i was loading the stack pointer itself, rather than the thing at the top of the stack

tribal warren
#

[SOLVED] getting return address in assembly

violet grove
#

lea just loads the address that the dereference would have accessed. It basically allows you to use the addressing semantics (adding registers, scaling by small powers of two, etc.) for plain arithmetic

#

So lea rcx, [rsp] is basically just mov rcx, rsp

#

But you can do e.g. lea rax, [rdi+rsi] to do a RISC-style 3-operand add (rax = rdi + rsi)