Linux 汇编代码无法识别?和@数据
这是我的第一个汇编程序。 请任何人帮助它成功运行。 我看到下面的编译错误 为什么它不承认这一点?和@数据? 我试图在汇编中交换两个变量 我正在执行以下命令Linux 汇编代码无法识别?和@数据,linux,assembly,x86,nasm,Linux,Assembly,X86,Nasm,这是我的第一个汇编程序。 请任何人帮助它成功运行。 我看到下面的编译错误 为什么它不承认这一点?和@数据? 我试图在汇编中交换两个变量 我正在执行以下命令 nasm -f elf swap.asm 但我得到了这个错误: swap.asm:6: error: symbol `?' undefined swap.asm:12: error: symbol `@data' undefined swap.asm:15: error: invalid combination of opcode and
nasm -f elf swap.asm
但我得到了这个错误:
swap.asm:6: error: symbol `?' undefined
swap.asm:12: error: symbol `@data' undefined
swap.asm:15: error: invalid combination of opcode and operands
swap.asm:21: error: invalid combination of opcode and operands
swap.asm:22: error: invalid combination of opcode and operands
这是我的代码:
section .data
C equ 15
var1 db 12
section .bss
var2 db ?
section .code
global _start
_start:
mov ax, @data
mov ds, ax
mov var2, C
; swap var1 and var2
mov al, var1
mov bl, var2
mov var2, al
mov var1, bl
; now print the swapped values
mov eax, 4 ; 4 = sys_write
mov ebx, 1 ; 1 - std out FD
mov ecx, var1
mov edx, 8
int 80h
mov eax, 4 ; 4 = sys_write
mov ebx, 1 ; 1 - std out FD
mov ecx, var2
mov edx, 8
int 80h
; exit the program
mov eax, 1 ; 1 = sys_exit
mov ebx, 0
int 80h
此代码表示您可能从MASM教程中复制并粘贴了16位代码:
mov ax, @data
mov ds, ax
在Linux上,模型是扁平的,因此此代码是不必要的,可以删除。由于您是使用NASM编译的,因此当您希望访问内存地址处的数据时,必须将[]放在内存引用周围,这与MASM不同。所以代码如下:
mov al, var1
应该是:
mov al, [var1]
在第2.2节MASM用户快速入门中,提供了有关NASM和MASM语法之间差异的有用信息。我已在本修订规范中记录了许多其他要求的变更:
section .data
C equ 15
var1: db 12 ; NASM needs a colon after labels unlike MASM
section .bss
var2: resb 1 ; NASM doesn't have '?'. Use RESB to allocate space
; in BSS section. RESB 1 allocates 1 byte of space
section .text ; The code section in ELF is `.text` and not `.code`
global _start
_start:
mov byte [var2], C ; C doesn't need brackets because it was defined with EQU
; and is a constant (immediate) value.
; NASM can't determine the size of a constant
; nor does it know the size of data at var2
; so the BYTE directive is used on the memory operand.
; swap var1 and var2
mov al, [var1] ; Getting data from var1 - brackets needed
mov bl, [var2] ; Getting data from var2 - brackets needed
mov [var2], al ; Changing value at var2 - brackets needed
mov [var1], bl ; Changing value at var1 - brackets needed
; now print the swapped values
mov eax, 4 ; 4 = sys_write
mov ebx, 1 ; 1 - std out FD
mov ecx, var1 ; No brackets because we want the address of var1
mov edx, 1 ; Print 1 byte
int 80h
mov eax, 4 ; 4 = sys_write
mov ebx, 1 ; 1 - std out FD
mov ecx, var2 ; No brackets because we want the address of var1
mov edx, 1 ; Print 1 byte
int 80h
; exit the program
mov eax, 1 ; 1 = sys_exit
mov ebx, 0
int 80h
如果您运行此代码,它可能看起来没有打印您期望的内容。SYS_write系统调用不打印整数-它打印字符串。如果要写入值12或15,则需要将数字转换为字符串,然后将字符串的地址传递给SYS_write系统调用。对于将整数转换为字符串的32位解决方案,您可以查看其答案。Peter Cordes的另一个相关答案还有其他。此代码表示您可能从MASM教程中复制并粘贴了16位代码:
mov ax, @data
mov ds, ax
在Linux上,模型是扁平的,因此此代码是不必要的,可以删除。由于您是使用NASM编译的,因此当您希望访问内存地址处的数据时,必须将[]放在内存引用周围,这与MASM不同。所以代码如下:
mov al, var1
应该是:
mov al, [var1]
在第2.2节MASM用户快速入门中,提供了有关NASM和MASM语法之间差异的有用信息。我已在本修订规范中记录了许多其他要求的变更:
section .data
C equ 15
var1: db 12 ; NASM needs a colon after labels unlike MASM
section .bss
var2: resb 1 ; NASM doesn't have '?'. Use RESB to allocate space
; in BSS section. RESB 1 allocates 1 byte of space
section .text ; The code section in ELF is `.text` and not `.code`
global _start
_start:
mov byte [var2], C ; C doesn't need brackets because it was defined with EQU
; and is a constant (immediate) value.
; NASM can't determine the size of a constant
; nor does it know the size of data at var2
; so the BYTE directive is used on the memory operand.
; swap var1 and var2
mov al, [var1] ; Getting data from var1 - brackets needed
mov bl, [var2] ; Getting data from var2 - brackets needed
mov [var2], al ; Changing value at var2 - brackets needed
mov [var1], bl ; Changing value at var1 - brackets needed
; now print the swapped values
mov eax, 4 ; 4 = sys_write
mov ebx, 1 ; 1 - std out FD
mov ecx, var1 ; No brackets because we want the address of var1
mov edx, 1 ; Print 1 byte
int 80h
mov eax, 4 ; 4 = sys_write
mov ebx, 1 ; 1 - std out FD
mov ecx, var2 ; No brackets because we want the address of var1
mov edx, 1 ; Print 1 byte
int 80h
; exit the program
mov eax, 1 ; 1 = sys_exit
mov ebx, 0
int 80h
如果您运行此代码,它可能看起来没有打印您期望的内容。SYS_write系统调用不打印整数-它打印字符串。如果要写入值12或15,则需要将数字转换为字符串,然后将字符串的地址传递给SYS_write系统调用。对于将整数转换为字符串的32位解决方案,您可以查看其答案。Peter Cordes的另一个相关答案还有另外一个。您有16位代码和32位代码的混合,其中一些代码是MASM语法,其余的是NASM。我认为下面两条指令的操作数大小不同。解决方案应该是什么?我应该使用cl而不是ecx吗?mov ecx,var1 mov ecx,VAR2您有16位代码和32位代码的混合,其中一些代码是MASM语法,其余是NASM。我认为下面两条指令的操作数大小不同。解决方案应该是什么?我应该使用cl而不是ecx吗?mov ecx,var1 mov ecx,VAR2对于最后一部分,有at Does部分的工作代码。代码在这里实际工作吗?发现它不适用于x86-64 Linux,该未知节名被链接到一个不可执行的段中。可能ld默认值已更改,并且没有将.rodata放入文本段。嗯,我刚刚测试了这段代码,它确实用两个单独的系统调用写入了\17和\f字节,而不是segfaulting。我认为这段代码只在32位模式下工作,因为缺少一个PT_GNU__堆栈注释,导致仍然获得exec all,或者可能这只是execstack处理的一个副作用,在没有PT_GNU_堆栈的情况下,您可以在32位可执行文件中获得exec all,而不仅仅是x86-64中的exec堆栈:对于最后一部分,有at Does部分的工作代码。代码在这里实际工作吗?发现它不适用于x86-64 Linux,该未知节名被链接到一个不可执行的段中。可能ld默认值已更改,并且没有将.rodata放入文本段。嗯,我刚刚测试了这段代码,它确实用两个单独的系统调用写入了\17和\f字节,而不是segfaulting。我认为这段代码只在32位模式下工作,因为缺少一个PT_GNU__堆栈注释,导致仍然获得exec all,或者可能这只是execstack处理的一个副作用,在没有PT_GNU_堆栈的情况下,您可以在32位可执行文件中获得exec all,而不仅仅是x86-64中的exec堆栈: