问题
I have this FASM code:
msg1:
db "hello", 0
msg1_len equ $ - msg1 ; should be 6
Then later in code, mov edx, msg1_len
puts its value in a register.
Although msg1_len is supposed to be 6, when I'm debugging it, it returns a strange big number such as 4570. that is, "msg1_len" is equal to 4570
In other applications it's same -- a big, random-looking number instead of the length of a string.
Why is this? How to fix it?
回答1:
TL:DR: in FASM, equ
is a text substitution, like NASM %define
.
FASM len = $ - msg1
evaluates once, on the spot. (Like equ
in most other assemblers, and also like =
in MASM and GAS).
Text substitution breaks because $ - msg1
is context-sensitive: $
is the current position so mov edx, $ - msg1
is some large size that depends on the position of the instruction. equ
would be fine for something like 8 * myconst
in most cases.
EDIT: ooops.... I did use =
, not equ
.
When I replaced =
with equ
, I get compile error:
helloworld.asm [13]:
mov edx,msg1_size ; Length of message
error: undefined symbol 'msg1_size'.
(flat assembler version 1.71.51)
Works for me, when I put it into compilable FASM example, I get 6
.
The full code I used to verify it works correctly:
format ELF executable 3
entry start
;================== code =====================
segment readable executable
;=============================================
start:
mov eax,4 ; System call 'write'
mov ebx,1 ; 'stdout'
mov ecx,msg1 ; Address of message
mov edx,msg1_size ; Length of message
^^ this compiles as mov edx,6
, verified in debugger.
int 0x80 ; All system calls are done via this interrupt
mov eax,1 ; System call 'exit'
xor ebx,ebx ; Exitcode: 0 ('xor ebx,ebx' saves time; 'mov ebx, 0' would be slower)
int 0x80
;================== data =====================
segment readable writeable
;=============================================
msg1:
db 'hello', 0
msg1_size = $-msg1
final(?) update:
Check FASM docs about 2.2.1 Numerical constants:
The
=
directive allows to define the numerical constant. It should be preceded by the name for the constant and followed by the numerical expression providing the value. The value of such constants can be a number or an address, but - unlike labels - the numerical constants are not allowed to hold the register-based addresses. Besides this difference, in their basic variant numerical constants behave very much like labels and you can even forward-reference them (access their values before they actually get defined).
vs 2.3.2 Symbolic constants:
The symbolic constants are different from the numerical constants, before the assembly process they are replaced with their values everywhere in source lines after their definitions, and anything can become their values.
The definition of symbolic constant consists of name of the constant followed by the
equ
directive. Everything that follows this directive will become the value of constant. If the value of symbolic constant contains other symbolic constants, they are replaced with their values before assigning this value to the new constant.
Conclusion: so you should use =
instead of equ
(in FASM).
(for calculating numeric constants I mean.. you can still use equ
for symbolic constants... sounds to me like macro definition)
You got your big constant because you had that symbol defined ahead of code, and during compilation it did something like mov edx,$ - msg1
, where $
is already address of the instruction, not your placement of msg1_len
definition.
来源:https://stackoverflow.com/questions/46783331/a-wrong-size-of-len-calculated-by-symbol-with-fasm-equ