【问题标题】:Assembly code do not recognise ? and @data汇编代码不识别?和@data
【发布时间】:2019-12-10 11:11:49
【问题描述】:

这是我的第一个汇编程序。
任何人都可以帮助使其成功运行。
我看到下面的编译错误。

为什么它无法识别?@data
我正在尝试在程序集中交换两个变量。

我正在执行以下命令

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

【问题讨论】:

  • 你有 16 位代码和 32 位代码的混合体,其中一些代码是 MASM 语法,其余的是 NASM。
  • 我认为对于以下两条指令,操作数的大小不同。应该是什么解决方案,我应该使用 cl 而不是 ecx 吗? mov ecx, var1 mov ecx, var2

标签: linux assembly x86 nasm


【解决方案1】:

此代码表明您可能从 16 位代码的 MASM 教程中复制并粘贴了它:

mov ax, @data
mov ds, ax

在 Linux 上,模型是扁平的,因此此代码是不必要的,可以删除。由于您使用 NASM 进行编译,因此当您希望访问内存地址处的数据时,您必须在内存引用周围放置 [](与 MASM 不同)。所以代码如下:

mov al, var1

应该是:

mov al, [var1]

NASM documentation2.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 位解决方案,您可以查看此related question 的答案。 Peter Cordes 的另一个相关答案还有其他useful information

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-26
  • 2011-05-20
  • 1970-01-01
  • 2014-03-24
  • 2014-02-03
相关资源
最近更新 更多