问题
It is my first assembly program.
Can anyone please help to make it run successfully.
I am seeing below compilation error.
Why it do not recognize the ?
and @data
?
I am trying to swap two variables in assembly.
I am executing the following command
nasm -f elf swap.asm
But I get this error:
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
This is my code:
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
回答1:
This code indicates you have probably copy and pasted it from a MASM tutorial for 16-bit code:
mov ax, @data
mov ds, ax
On Linux the model is flat so this code is unnecessary and can be removed. Since you are compiling with NASM you have to place []
around memory references (unlike MASM) when you wish to access the data at a memory address. So code like:
mov al, var1
Should be:
mov al, [var1]
The NASM documentation has useful information on differences between NASM and MASM syntax in section 2.2 Quick Start for MASM Users. I have documented a number of other required changes in this revised code:
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 .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
If you run this code it may appear to not print what you expect. The SYS_write
system call doesn't print integers - it prints strings. If you want to write the value 12 or 15 you would need to convert the number to a string and then pass the address of the string to SYS_Write
system call. For a 32-bit solution that converts integer to string you can look at the answers to this related question. Another related answer by Peter Cordes has other useful information.
来源:https://stackoverflow.com/questions/57316059/assembly-code-do-not-recognise-and-data