Linux Bss部分-->;无效的操作数组合

Linux Bss部分-->;无效的操作数组合,linux,assembly,nasm,Linux,Assembly,Nasm,我在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 o

我在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新手

我希望你能回应我


tfphd

如果要在
中声明内存内容。数据

section .data
HALLO: db 'HALLO'
您将创建:

  • 从编译点开始:一个名为
    HALLO
    的符号,其中包含指向
    'H'
    字符的地址
  • 从linux可执行文件的角度来看:5字节长的数组,包含字节
    72,65,76,76,79
    ,位于读写初始化(通过加载可执行文件一次)内存区域
因此,现在您可以执行以下操作:

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
部分中创建它,那么尝试修改它是不明智的。有关详细信息,请参阅

如果在
.bss
中创建该数组,则应取消初始化该数组,就像最初一样,将可执行文件加载到内存中只会保留该空间,而不会对其进行初始化

您不能做
mov-HALLO,“HALLO”
,x86汇编程序不是这样工作的。 最接近它的是
mov-DWORD[HALLO],'HALL'
mov-BYTE[HALLO+4],'O'
。在32b模式下,单条指令不能存储5个字节

因此,如果要将某个内存数组设置为某个初始值字符串,可以使用
.data
部分,并在初始文本字节后添加行
乘以64 db 0
,将其放大64字节(以便以后可以用更长的字符串覆盖)如果希望每次可执行文件运行时初始化一次

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

顺便说一句,注意在这样的例子中,用符号HALLO命名值“HALLO”是多么的笨拙,因为现在您必须特别注意识别我在哪里谈论标签(符号/地址),以及我在哪里使用它作为文字值(字节)

总的来说,如果您刚开始使用ASM,请从字符串移动到数字(不要尝试输出它们,只需在调试器中运行并通过调试器查看寄存器/内存值)

熟悉字节/字/dword、地址和基本算术指令后,检查字符串在内存中的编码方式(ASCII/UTF-8/UTF-16),以及从数字机器(CPU)的位置看它是什么样子。或者遵循任何nasm教程,它很可能从一些“hello world”开始显示,这可能无法深入解释为什么神奇的
db'helloworld',10
可以作为int 80h的字符串(eax,4;…)


最后,
x86
标记上的信息非常大,包含许多其他资源:

如果您要在
中声明内存内容。data

section .data
HALLO: db 'HALLO'
您将创建:

  • 从编译点开始:一个名为
    HALLO
    的符号,其中包含指向
    'H'
    字符的地址
  • 从linux可执行文件的角度来看:5字节长的数组,包含字节
    72,65,76,76,79
    ,位于读写初始化(通过加载可执行文件一次)内存区域
因此,现在您可以执行以下操作:

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
部分中创建它,那么尝试修改它是不明智的。有关详细信息,请参阅

如果在
.bss
中创建该数组,则应取消初始化该数组,就像最初一样,将可执行文件加载到内存中只会保留该空间,而不会对其进行初始化

您不能做
mov-HALLO,“HALLO”
,x86汇编程序不是这样工作的。 最接近它的是
mov-DWORD[HALLO],'HALL'
mov-BYTE[HALLO+4],'O'
。在32b模式下,单条指令不能存储5个字节

因此,如果要将某个内存数组设置为某个初始值字符串,可以使用
.data
部分,并在初始文本字节后添加行
乘以64 db 0
,将其放大64字节(以便以后可以用更长的字符串覆盖)。-如果希望每次可执行运行时初始化一次

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

顺便说一句,注意在这样的例子中,用符号HALLO命名值“HALLO”是多么的笨拙,因为现在您必须特别注意识别我在哪里谈论标签(符号/地址),以及我在哪里使用它作为文字值(字节)

总的来说,如果您刚开始使用ASM,请从字符串移动到数字(不要尝试输出它们,只需在调试器中运行并通过调试器查看寄存器/内存值)

熟悉字节/字/dword、地址和基本算术指令后,检查字符串在内存中的编码方式(ASCII/UTF-8/UTF-16),以及从数字机器(CPU)的位置看它是什么样子。或者遵循任何nasm教程,它很可能从一些“hello world”开始显示,这可能无法深入解释为什么神奇的
db'helloworld',10
可以作为int 80h的字符串(eax,4;…)


最后,
x86
标记上的信息非常大,包含许多f