-2

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?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Kojito
  • 9
  • 1
  • 4
    You have to show us the code that tries to use msg1_len and/or what comamnds you are using in the debugger to display the value. Showing us your complete code would be beneficial. – Michael Petch Oct 17 '17 at 06:04
  • Looks correct to me, unless `msg1_len` is in a different section from `msg1`. (Or there are other non-zero-size things between it and `msg1`.) – Peter Cordes Oct 17 '17 at 08:03
  • @PeterCordes, the same section, next to each other – Kojito Oct 17 '17 at 08:14
  • @PeterCordes, I'm using it right – Kojito Oct 17 '17 at 08:56
  • 1
    The FASM manual (https://flatassembler.net/docs.php?article=manual) says `$` works the same as NASM, so either FASM is buggy or you're using it wrong. Stop trolling us and post the code you used to get the value. Try `mov eax, msg1_len`, and look at the disassembly. (And/or the machine code, remembering that x86 immediates are little-endian). – Peter Cordes Oct 17 '17 at 08:59
  • 1
    Hey there, you're asking for help here, no need to be rude to someone trying to help you improve your question. – LW001 Oct 17 '17 at 09:04

1 Answers1

2

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.

Community
  • 1
  • 1
Ped7g
  • 16,236
  • 3
  • 26
  • 63
  • So `equ` is acting like a text substitution, and evaluating `$` at the position that uses `msg1_size`? That would explain the large number the OP was getting. Oops, I guess this question was answerable after all. – Peter Cordes Oct 17 '17 at 11:34
  • 1
    @PeterCordes took me completely by surprise (as I don't know anything about FASM). Sometimes it helps to try to repeat steps of OP (with the limited info they provide), to find out if there's some merit to their question. Well, it's never late to learn something new, especially if you forget things quickly, you can learn new things basically every morning... (now I'm going to figure out what is that funny tube with name "toothpaste" good for) – Ped7g Oct 17 '17 at 11:36
  • 1
    And BTW, you obviously need to put the `equ` lines before the code that uses them. I guess in FASM, it's a good idea to put your data and numeric constants at the bottom of your file, so it's an assemble-time error if you use `equ` where you should have used `=`, instead of getting a wrong constant. – Peter Cordes Oct 17 '17 at 11:38