Bss 段 --> 无效的操作数组合

Bss section --> invalid combination of operands

我在 Linux.

下编程 nasm 遇到了问题

我的问题是

/home/maximilian/Schreibtisch/Programmierung/meinCompiler/var2.asm:6:  warning: character constant too long
    /home/maximilian/Schreibtisch/Programmierung/meinCompiler/var2.asm:6: error: invalid combination of opcode and operands
    /usr/bin/ld: cannot find /home/maximilian/Schreibtisch/Programmierung/meinCompiler/var2.o: Datei oder Verzeichnis nicht gefunden

我的nasm代码:

section .data

section .text
global _start:
_start:
mov HALLO, "HALLO"
mov eax, 1
mov ebx, 0
int 0x80

section .bss
HALLO: resb 4  

有人能帮帮我吗?

我搜索过这个主题,但没有找到任何关于 NASM-newb

的综合信息

希望你能回复我,

tfphd

如果在.data中声明内存内容:

section .data
HALLO: db 'HALLO'

您将创建:

  • 从编译点开始:一个名为 HALLO 的符号,其中包含指向 'H' 字符的地址
  • 从 linux 可执行文件开始:包含字节 72,65,76,76,79 的 5 字节长数组,在读取-写入 初始化(通过加载可执行文件一次)内存区域.

现在您可以执行以下操作:

mov   eax,HALLO                    ; loads value of symbol HALLO into register eax
  ; value of symbol HALLO is address of that array
mov   DWORD [eax+2],0x454D504C     ; writes number over 'LLO?' in that array
  ; creating string 'HALPME' in memory at address HALLO
  ; BUG: notice how 1 character is overwritten after the original array
  ; this may overwrite and destroy some other important value in .data

如果您要在 .rodata 部分中创建它,则尝试修改它是不明智的。有关详细信息,请参阅 NASM sections manual

如果您在 .bss 中创建它,则数组应该未初始化,就像您最初所做的那样,将可执行文件加载到内存中只会保留 space,但不会对其进行初始化。

你不能这样做 mov HALLO, "HALLO",那不是 x86 程序集的工作方式。 最接近的是mov DWORD [HALLO],'HALL'mov BYTE [HALLO+4],'O'。在 32b 模式下,单条指令不能存储 5 个字节。

所以如果你想将一些内存数组设置为一些初始值字符串,要么使用 .data 部分,并在初始文本字节后添加行 times 64 db 0 以将其扩大 64 个字节(因此您可以稍后用更长的字符串覆盖它)。 - 如果你希望每个可执行文件初始化一次 运行.

或者将 'HALLO' 放入 .rodata 中,使用某种机制标记字符串的长度(在某处将其作为数字 5,或者在 O 之后添加第 6 个字节 0 或其他一些终止符($ 在 DOS 中用于 int 21h)。并在 .bss 中创建足够长的缓冲区,如 stringBuffer: resb 69。然后每次你想将它设置为 'HALLO',你必须复制从地址 HALLO 到地址 stringBuffer.

的 5 个字节

顺便说一句,请注意在这样的例子中用符号 HALLO 命名值 'HALLO' 是多么的尴尬,因为现在你必须格外注意识别我在哪里谈论标签 (symbol/address) ,以及我将其用作文字值(字节)的地方。

总的来说,如果您刚开始使用 ASM,请从字符串转向数字(不要尝试输出它们,只需在调试器中 运行 并通过调试器观察 register/memory 值) .

熟悉byte/word/dword、地址和基本算术指令后,再看看字符串在内存中是如何编码的(ASCII/UTF-8/UTF-16),从数字机的位置看是怎样的( CPU)。或者按照任何 nasm 教程,它很可能会以一些 "hello world" 显示开始,这可能不会深入解释,为什么那个魔法 db 'hello world',10 作为字符串与 int 80h (eax,4 ;...).


最后,x86 标签上的信息非常大,包含许多进一步的资源:
https://whosebug.com/tags/x86/info