flat assembler
Message board for the users of flat assembler.

Index > Main > call usage howto?

Author
Thread Post new topic Reply to topic
songjiangshan



Joined: 16 Dec 2022
Posts: 5
songjiangshan 16 Dec 2022, 13:14
i don't know where can find the call usage.
i find that:


Code:

format PE64 console
include 'win64wx.inc' ;

entry main 

section '.text' code readable executable

main:
mov rbp, rsp
and rsp, -16
sub rsp, 32

call  a
call [ExitProcess]

ret

a:
push rbp
mov rbp, rsp

sub rsp, 32

push rcx
push rdx
pop rcx
pop rdx
add rsp, 32

pop rbp
ret
;endp


section '.idata' data readable import
library kernel32, 'kernel32.dll', msvcrt,   'msvcrt.dll',shell,'SHELL32.DLL'
import kernel32, GetCommandLine,'GetCommandLineA', \
ExitProcess,'ExitProcess'
    



call function myself, i have to use



Code:
 
call a

    



call system function, i have to use:


Code:
call [ExitProcess]


    



or i will meet c0000005 error.
but what is the different?
or i use the call in a wrong way?

further test:

Code:
format PE64 console
include 'win64wx.inc' ;

entry main 

section '.text' code readable executable

main:
mov rbp, rsp
and rsp, -16


;this works fine
;call a

;------------------------------------------
;why?? this error
;lea rax, [a]
;call qword [rax]
;------------------------------------------



;this works fine:
;call [ExitProcess]

; this works fine
;lea rax, [ExitProcess]
;call qword [rax]

;this works fine.
;mov rax, ExitProcess
;call qword [rax]

;this call error: because ExitProcess is a pointer variable?
;mov rax, [ExitProcess]
;call qword [rax]

; this error. as inner a is the code, not the address.
;mov rax, [a]
;call qword [rax]

;this error. as inner a is the code, not the addres.
;mov rax, a
;call qword [rax]



ret

a:

ret

section '.data' data readable writeable
eee db 'abc',0


section '.idata' data readable import
library kernel32, 'kernel32.dll', msvcrt,   'msvcrt.dll',shell,'SHELL32.DLL'
import kernel32, GetCommandLine,'GetCommandLineA', \
ExitProcess,'ExitProcess'





    


Description:
Filesize: 27.89 KB
Viewed: 3037 Time(s)

tmp1.png


Post 16 Dec 2022, 13:14
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2595
Furs 16 Dec 2022, 14:17
Code:
call a    
encodes a relative offset to the label a, so it works because it's always loaded at a fixed offset in your output binary (it's your function in your code).

Code:
call [ExitProcess]    
first obtains the 64-bit qword at where ExitProcess is (which is in the import address table), then calls that value, which has the 64-bit address of the code in the system library. So it's an indirect call.

You might ask why is the indirection needed? Because you don't know where the system library will be loaded. It's not fixed relative to your code.

So the OS has an "import address table" that is a list of addresses for such functions that gets filled in when the library gets loaded. What the executable stores is info about the function, such as its name (ExitProcess). It then looks it up and fills the value at [ExitProcess] with its actual address, so you can call it in code.

So "ExitProcess" itself does not point to the system code, it points to the import address in your binary. It's the qword value obtained from where it points to that points to the system code.

If you wanted something similar with "a" you'd do e.g.:
Code:
lea rax, [a]
mov [MyIndirectVar], rax
...
call [MyIndirectVar]
...


MyIndirectVar dq 0    
Post 16 Dec 2022, 14:17
View user's profile Send private message Reply with quote
songjiangshan



Joined: 16 Dec 2022
Posts: 5
songjiangshan 16 Dec 2022, 14:25
thanks.
but why can't we just do this:

;lea rax, [a]
;call qword [rax]


while we can do this:

;mov rax, ExitProcess
;call qword [rax]



Furs wrote:
Code:
call a    
encodes a relative offset to the label a, so it works because it's always loaded at a fixed offset in your output binary (it's your function in your code).

Code:
call [ExitProcess]    
first obtains the 64-bit qword at where ExitProcess is (which is in the import address table), then calls that value, which has the 64-bit address of the code in the system library. So it's an indirect call.

You might ask why is the indirection needed? Because you don't know where the system library will be loaded. It's not fixed relative to your code.

So the OS has an "import address table" that is a list of addresses for such functions that gets filled in when the library gets loaded. What the executable stores is info about the function, such as its name (ExitProcess). It then looks it up and fills the value at [ExitProcess] with its actual address, so you can call it in code.

So "ExitProcess" itself does not point to the system code, it points to the import address in your binary. It's the qword value obtained from where it points to that points to the system code.

If you wanted something similar with "a" you'd do e.g.:
Code:
lea rax, [a]
mov [MyIndirectVar], rax
...
call [MyIndirectVar]
...


MyIndirectVar dq 0    
Post 16 Dec 2022, 14:25
View user's profile Send private message Reply with quote
songjiangshan



Joined: 16 Dec 2022
Posts: 5
songjiangshan 16 Dec 2022, 14:39
@Furs
thanks, be figured out:


;this works fine
;call a

;this works too
;lea rax, [a]
;mov [MyIndi​​rectVar], rax
;lea rax, [MyIndi​​rectVar]
;call qword [MyIndi​​rectVar]

; this works three
;lea rax, [a]
;mov [MyIndi​​rectVar], rax
;lea rax, [MyIndi​​rectVar]
;call qword [rax]


;this do not work:
;lea rax, [a]
;call qword [rax]
Post 16 Dec 2022, 14:39
View user's profile Send private message Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1692
Location: Toronto, Canada
AsmGuru62 16 Dec 2022, 17:29
There are very useful macro statements in the file "win64...inc".
There is macro 'invoke' which will solve your calls properly.
You also using your own function prologue/epilogue -- there are macro proc/endp which take care of local variables and stack alignment.
Why not use those?
Post 16 Dec 2022, 17:29
View user's profile Send private message Send e-mail Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2595
Furs 17 Dec 2022, 18:51
songjiangshan wrote:
@Furs
thanks, be figured out:


;this works fine
;call a

;this works too
;lea rax, [a]
;mov [MyIndi​​rectVar], rax
;lea rax, [MyIndi​​rectVar]
;call qword [MyIndi​​rectVar]

; this works three
;lea rax, [a]
;mov [MyIndi​​rectVar], rax
;lea rax, [MyIndi​​rectVar]
;call qword [rax]


;this do not work:
;lea rax, [a]
;call qword [rax]
Yes as I said, ExitProcess is not a label to the code itself, it's more like a label to a pointer:
Code:
ExitProcess dq actual_address_to_the_function_after_runtime_load    
i.e. it's like MyIndi​​rectVar, not "a".
Post 17 Dec 2022, 18:51
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.