NASM - 将常量定义为EXTERN

时间:2014-03-11 15:21:12

标签: nasm

从逻辑上讲,我想要做的是:

      GLOBAL  FRED
FRED  EQU     5

在一个模块中,

      EXTERN  FRED
      MOV     ECX,FRED

一秒钟。

我知道

第一个模块

      GLOBAL  FRED
FRED: DD      5

第二个模块

      EXTERN  FRED
      MOV     ECX,[FRED]

非常愉快地工作,但我真正喜欢的是第一个版本。

我已经尝试了

FRED  EQU     5
FRED: EQU     5
%define FRED  5
%assign FRED  5

无效 - 没有错误消息,但未导出标签。只有FRED是地址才能合作。

那么 - 有没有办法将一个模块中的值作为常量导出,而不是地址?

3 个答案:

答案 0 :(得分:2)

简短回答:不。

您不能使用equ,define或assign进行导出,因为它们不会在编译模块中显示为单独的值。它们只影响预处理器,所以写

   FRED equ 5
   mov  ecx, FRED

实际编译为

   mov  ecx, 5

通常的做法是使用包含所有常量的C样式头文件,然后只在需要的地方包含头文件。

fred.asm:

   %ifndef FRED_ASM
     %define FRED_ASM

       %define FRED 5
       ; ... other constants ...

   %endif

module.asm

   %include "fred.asm"

   mov ecx, FRED

答案 1 :(得分:1)

如果我理解正确,您希望FRED在某处定义并被许多模块/源文件使用?每个模块/源文件使用FRED而不是更改每个源文件中的值并重新组装每个文件,只需更改一个FRED实例并让它在任何地方使用?如果是这种情况,您可以将equ ates放入静态库并链接到它。这不适用于%define,仅适用于equ

试试这个:
libequates.asm

global FRED, JOHN

FRED    equ 5
JOHN    equ 6

makefile for libequates.asm(根据需要进行修改)

LIBRARY = libequates

all: $(LIBRARY) PostMake

$(LIBRARY): $(LIBRARY).o 
    ar -cr $(LIBRARY).a $(LIBRARY).o
    strip --strip-unneeded $(LIBRARY).a

$(LIBRARY).o: $(LIBRARY).asm
    nasm -f elf64 $(LIBRARY).asm -F dwarf   

PostMake:
    mkdir -p ~/projects/lib/
    mv $(LIBRARY).a ~/projects/lib

现在使用并测试它是否有效(为简单起见,我将使用printf):

externs.asm

extern FRED, JOHN, printf, exit

global start

section .data
fmtint      db  "%d", 10, 0

section .text
start:
    mov     rsi, FRED
    mov     rdi, fmtint
    xor     rax, rax
    call    printf

    mov     rsi, JOHN
    mov     rdi, fmtint
    xor     rax, rax
    call    printf

    mov     rdi, 0
    call    exit

makefile for externs.asm

APP = externs

all: $(APP) clean

$(APP): $(APP).o 
    ld  -o $(APP) $(APP).o -entry start -L ~/projects/lib -lequates -lc -dynamic-linker /lib64/ld-linux-x86-64.so.2

$(APP).o: $(APP).asm
    nasm -f elf64 $(APP).asm -F dwarf

clean:
    rm $(APP).o

并输出:
enter image description here

现在,您只需要在一个地方更改equate值,只重新组装静态库并重新链接您的程序/模块。

答案 2 :(得分:1)

Nasm将点字符("。")视为符号名称中的合法字符。 您可以使用它来伪造COM(组件对象模型)"对象属性"。 如果你有3个模块,每个模块都有一个"宽度"变量,你可以拉下面的特技:

;ButtonWidget
    SECTION .data
    global ButtonWidget.width, ButtonWidget.height
    ButtonWidget:
       .width dd 50
       .height dd 10

;SelectWidget
    SECTION .data
    global SelectWidget.width, SelectWidget.height
    SelectWidget:
       .width dd 50
       .height dd 100

;TextWidget
    SECTION .data
    global TextWidget.width, TextWidget.height
    TextWidget:
       .width dd 200
       .height dd 10

在您的主模块中,

;GUIapp
extern ButtonWidget.width, ButtonWidget.height
extern SelectWidget.width, SelectWidget.height
extern TextWidget.width, TextWidget.height
%macro MakeChildWindow 4
push %1
push %2
push %3
push %4
call makechildwindow
%endmacro
MakeChildWindow 10, 10, ButtonWidget.width, ButtonWidget.height
MakeChildWindow 10, 30, SelectWidget.width, SelectWidget.height
MakeChildWindow 10, 200, TextWidget.width, TextWidget.height

该技术的优点是可以修复外部变量 或者是可变的,而且非常易读。