A wrong size of “len” calculated by $ - symbol with FASM EQU [closed]

时光毁灭记忆、已成空白 提交于 2019-12-08 14:00:14

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!