Explain the difference between assemblers and MASM FASM. Yurov studying a book with practical algorithms in assembly language, and decided to write them on the FASM, because they say it gives more opportunities. The first thing that did not like – an extra import section with garbage inside, without which I treated before, and the need to put the byte ptr where in MASM not required. FASM seems excessive.
Finally, a simple example from the book fulfills very strange:
format PE Console 4.0
entry start
include 'win32a.inc'
section '.text' code readable executable
start:
call add_uint
proc add_uint
mov al, byte ptr a
add al, 10
jnc end_p
adc byte ptr carry, 0
end_p:
ret
endp
exit:
invoke ExitProcess, 0
section '.data' data readable writeable
a db 255
b db 7
sum db 0
carry db 0
section '.idata' import data readable writeable
library kernel, 'kernel32.dll'
import kernel, ExitProcess, 'ExitProcess'
The debugger shows that after the ret in the procedure, we find ourselves again in the beginning of the procedure, it works off a second time, and only then proceed to the return address. Why is it so?
Answer 1, Authority 100%
The first thing that did not like – an extra import section with debris inside the
When I see questions on MASM, almost all of them have a bunch of junk include
. One change to another. On fasm can be written without explicitly specifying the import section, unless, of course, you do not need to call functions from libraries outside the “standard”.
Here hello.asm
from fasm package, as you can see, nothing “superfluous”:
format PE GUI 4.0
; example of simplified Windows programming using complex macro features
include 'win32ax.inc'; you can simply switch between win32ax, win32wx, win64ax and win64wx here
.code
start:
invoke MessageBox, HWND_DESKTOP, "Hi! I'm the example program!", invoke GetCommandLine, MB_OK
invoke ExitProcess, 0
.end start
the need to put the byte ptr where in MASM this was not required.
It is best to put square brackets, then the size will not have to be explicit. In your case, appeal to the variables can be changed to a:
mov al, [a]
...
adc [carry], 0
If the call goes to the entire variable, the “size” is not needed (size determined by the size of the variable). If there is an appeal, for example, one byte of dword variable size, you need to specify the byte size:
mov al, byte [a]
...
a dd 255
Address by some address in fasm denoted by the name of a variable or register in brackets. I think it is more logical than the way it is done in MASM dialect (if the address in the register – the brackets, if the address is in the variable – without them)
.
The details why it was decided to do so, see. In Design Principles (or why flat assembler is different?)
Just displacement (offset) is referred to as a variable name without brackets, ie mov eax, offset a
in the dialect fasm will look like mov eax, a
.
Finally, a simple example from the book fulfills a very strange
Of course, will be enough to work, if you put the function immediately after the call. processor code is carried out linearly (yet he does not meet the control transfer instruction) . Naturally, the return call after the processor encounters a function of who had just returned, and starts to perform it again.
If it is simplified, then the code of the function itself must be installed outside the code of other functions (above or below, it does not matter), or do JMP
Tag EXIT
immediately after Call
, since you started such a label, then “excess” execution of the add_uint
function will not be.
This is not the specificity of FASM, the same code for MASM will be performed the same.
And finally, the working example code for FASM. Please note that another file is connected via Include
, which allows you not to specify the import section explicitly (the import section will actually be added by the .end
macro):
Format PE CONSOLE 4.0
include 'win32ax.inc'
.code.
Proc Add_Uint.
MOV AL, [A]
Add Al, 10
JNC END_P.
ADC [CARRY], 0
end_p:
RET.
Endp.
Start:
call add_uint
INVOKE EXITPROCESS, 0
.data.
A DB 255.
B DB 7.
SUM DB 0.
CARRY DB 0.
.end start