在x86(NASM)中为变量赋值

3
我已经决定为了好玩而学习汇编语言。我已经用C语言编程多年了。
我遵循一些在线教程打印“Hello world”并在NASM手册中寻找了一些资料,这一切都很好。所以,我设定了一个任务:循环打印“hello world”。我知道我可以使用loop操作码来完成这个任务,但是希望能够显式编写并使用在.bss部分定义的变量。
然而,显然我误解了变量赋值在汇编中的工作原理,因为我得到了错误信息:
nasm -felf -o hello.o hello.asm
hello.asm:16: error: invalid combination of opcode and operands
hello.asm:17: error: invalid combination of opcode and operands
hello.asm:28: error: invalid combination of opcode and operands

我尝试在网上搜索有关变量赋值的信息,包括NASM手册,但似乎找不到我需要的信息。有人可以帮助吗?这是我的(简单!)代码:

; print "Hello world!" to the screen multiple times

section .data
    msg:    db  'Hello world!', 10
    msglen: equ $ - msg

section .bss
    iter:   resb    1

section .text
    global _start

_start:

    ; loop 10 times
    mov iter, 0     ; initalise loop counter
FL: cmp iter, 10    ; is iter == 10?
    jge LoopEnd

    ; write the message to STDOUT:
    mov eax,4       ; code for write syscall
    mov ebx,1       ; stdout fd
    mov ecx,msg     ; message to print...
    mov edx,msglen  ; ...and it's length
    int 80h         ; kernel interrupt

    ; increment loop iterator
    inc iter
    jp FL

LoopEnd:


    ; now exit, with return code 0:
    mov eax,1
    mov ebx,0
    int 80h
2个回答

8
要在NASM中进行内存引用,必须用方括号括起地址。此外,在这些情况下,您还需要指定大小,如下所示:
    mov byte [iter], 0     ; initalise loop counter
FL: cmp byte [iter], 10    ; is iter == 10?

    inc byte [iter]

在这种情况下,将 iter 存储在寄存器中而不是内存中可能更有意义。由于系统调用覆盖了大部分明显的寄存器,但是 esiedi 看起来是可用的。

1
谢谢 - 这样就解决了。这有点像C指针解引用,对吗?'iter'是地址,但[iter]是地址上的数据?是的吗?我不明白为什么需要告诉它iter是一个字节 - 我在.bss部分中定义了它为一个字节。不过我会在手册中查找答案!是的 - 我可以用寄存器来做,但我想使用来自.bss部分的变量来证明我能做到!谢谢。 - ccbunney
1
“iter”只是一个地址。具体来说,它是您使用“resb”初始化的那个字节的地址。因此,由您来指定您要进行多大的内存访问。这是汇编语言,没有什么是真正为您完成的。 :-) - Jonathon Reinhart

4
我认为必须用括号。尝试使用 [iter]
每当你遇到这样的问题,可以查看NASM文档
在本例中,请参阅有效地址部分:

有效地址是指向内存的任何操作数。在NASM中,有效地址具有非常简单的语法:它们由一个表达式组成,该表达式评估所需地址,并用方括号括起来。例如:

wordvar dw 123
mov ax,[wordvar]
mov ax,[wordvar+1]
mov ax,[es:wordvar+bx]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接