尺寸错误的"len"表示由$-用FASM EQU符号计算 [英] A wrong size of "len" calculated by $ - symbol with FASM EQU

查看:168
本文介绍了尺寸错误的"len"表示由$-用FASM EQU符号计算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下FASM代码:

  msg1:
      db "hello", 0

  msg1_len equ $ - msg1        ; should be 6

随后在代码中,mov edx, msg1_len将其值存储在寄存器中.

虽然msg1_len应该是6,当我调试它时,它返回一个奇怪的大数字,例如4570.也就是说,"msg1_len"等于4570

在其他应用程序中,它是相同的-一个看起来很随机的大数字,而不是字符串的长度.

这是为什么?如何解决?

解决方案

TL:DR:在FASM中,equ是文本替换,例如NASM %define.

FASM len = $ - msg1当场评估一次. (就像大多数其他汇编程序中的equ一样,在MASM和GAS中也像=一样.)

文本替换中断,因为$ - msg1是上下文相关的:$是当前位置,因此mov edx, $ - msg1的大小取决于指令的位置.在大多数情况下,equ对于8 * myconst之类的东西都很好.


糟糕....我确实使用了=,而不是equ.

当我用equ替换=时,出现编译错误:

helloworld.asm [13]:
        mov     edx,msg1_size      ; Length  of message
error: undefined symbol 'msg1_size'.

(扁平汇编程序1.71.51版)


为我工作,当我将其放入可编译的FASM示例中时,得到6.

我用来验证其正常工作的完整代码:

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

^^编译为mov edx,6,已在调试器中验证.

        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


最终(?)更新:

检查FASM文档有关 2.2.1数值常数:

=指令允许定义数字常数.它的前面应为常数的名称,然后是提供值的数字表达式.这些常量的值可以是数字或地址,但是-与标签不同-不允许数字常量保存基于寄存器的地址.除了这种区别之外,在它们的基本变体中,数字常量的行为与标签非常相似,您甚至可以向前引用它们(在实际定义它们之前访问它们的值).

vs 2.3.2符号常量:

符号常量与数值常量不同,在汇编过程之前,符号常量将在定义后的源代码行中将其替换为它们的值,并且任何东西都可以成为它们的值.

符号常量的定义由常量名称后跟equ指令组成.遵循该指令的所有内容都将成为常量的值.如果符号常量的值包含其他符号常量,则在将其分配给新常量之前,将其替换为它们的值.

结论:因此,您应该使用=代替equ(在FASM中).

(用于计算数值常量,我的意思是..您仍然可以将equ用作符号常量...对我来说听起来像是宏定义)

之所以有一个大常量,是因为您在代码之前定义了该符号,并且在编译过程中它做了类似mov edx,$ - msg1的操作,其中$已经是指令的地址,而不是您放置的msg1_len定义./p>

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?

解决方案

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.

这篇关于尺寸错误的"len"表示由$-用FASM EQU符号计算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆