I am learning x64 ASM with NASM. I am getting an opcode and operand error. I can't find any really good documentation on it. It is difficult to find any documentation that explains it well enough.
; nasm/nasm -f macho64 -o asmtest.o asmtest.asm && ld -macosx_version_min 10.7.0 asmtest.o -o asmtest && ./asmtest
;
; External
;
; none
; Define
;
%define SYSCALL_WRITE 0x2000004
%define SYSCALL_EXIT 0x2000001
; Data
;
section .data
text db "Hi.", 0xA
textlen equ $ - text
section .bss
tmp resb 1
; Code
;
section .text
global start
start:
mov rax, 1
mov tmp, rax
call write
write:
mov rax, SYSCALL_WRITE
mov rdi, 1
mov rsi, text
mov rdx, textlen
syscall
call exit
exit:
mov rax, SYSCALL_EXIT
mov rdi, 1
syscall
My error I received was
asmtest.asm:32: error: invalid combination of opcode and operands
mov tmp, rax is illegal because nasm requires square brackets [] around memory operands. As such, what you want is mov [tmp], rax. This is of course mentioned in the nasm manual, see the section aptly named NASM Requires Square Brackets For Memory References.
Note however that rax is 64 bits, meaning 8 bytes, and you have only reserved 1 byte at tmp. In this case that might work, because nothing important seems to be after tmp in .bss, and page size works in your favor so you probably have space for your extra 7 bytes. Nevertheless you should really reserve as many bytes as you wish to use.
Related
This question already has an answer here:
glibc scanf Segmentation faults when called from a function that doesn't align RSP
(1 answer)
Closed 1 year ago.
I'm trying to call printf in nasm 64 bit linux. But it outputs segmentation fault when i run it. I alligned the stack, add a 0 escape character to the end of the string. But it still output segfault.
The code:
section .data
_DATA1 db "aa", 0
section .text
global main
extern printf
main:
sub rsp, 16
lea r13, [_DATA1]
mov rdi, r13
call printf
add rsp, 16
mov rax, 0
ret
assemble and link with
nasm -f elf64 a.asm
gcc -no-pie a.o
Where did i do something wrong?
Ok, i got it.
It turns out i need to add after main :
push rbp
mov rbp, rsp
So the code looks like this:
section .data
_DATA1 db "aa", 0
section .text
global main
extern printf
main:
push rbp
mov rbp, rsp
sub rsp, 16
lea r13, [_DATA1]
mov rdi, r13
call printf
add rsp, 16
mov rax, 0
mov rsp, rbp
pop rbp
ret
I realise that this is also what gcc do
I am working on a mac and writing an asm program supposed to printf its own source in another file with some modification, itself compile and run it. Therefor, I use the function system() to run a bash command.
Here is my problem, the line call _system works at a line, but a few lines later, nothing happen, its call seems to be ignored.
I made tests to be sure everything is fine, and it looks to be, I don't get error or whatever ... here is a sample :
section .data
i: equ 5
[...]
s_string: equ $ - string
name: db "Sully_%d.s", 0
s_name: equ $ - name
cc: db "nasm -fmacho64 Sully_%1$d.s -o Sully_%1$d.o", 0
s_cc: equ $ - cc
link: db "ld Sully_%1$d.o -o Sully_%1$d -macosx_version_min 10.8 -lSystem", 0
s_link: equ $ - link
ex: db "./Sully_%d", 0
s_ex: equ $ - ex
tmp: db "ls -l", 0
section .text
global start
global _main
extern _sprintf
extern _dprintf
extern _printf
extern _system
extern _close
extern _strlen
start:
call _main
ret
_main:
push rbp
mov rbp, rsp
sub rsp, 16
sub rsp, 0x650 ; 1616 byte to store strings later
mov rbx, i
cmp rbx, 0
je end_point
mov rdi, qword [rsi]
call _strlen
mov r12, rax
load_name:
lea rdi, [rbp + 16]
lea rsi, [rel name] ; string in data section, work fine since I can print it later at rbp + 16 location, I mean the result of 'name' string format with i as parameter
cmp r12, 7
jne ln_mov_i
mov rdx, i
cmp r12, 7
je ln_mov_i_1
ln_mov_i:
mov rdx, i - 1
ln_mov_i_1:
xor rax, rax
call _sprintf
cmp rax, 0
jl ret
load_cc:
lea rdi, [rel tmp]
call _system ; this does work
lea rdi, [rbp + 32 + s_name] ; string in data section, work fine since I can print it later
lea rsi, [rel cc]
cmp r12, 7
jne lc_mov_i
mov rdx, i
cmp r12, 7
je lc_mov_i_1
lc_mov_i:
mov rdx, i - 1
lc_mov_i_1:
xor rax, rax
call _sprintf
cmp rax, 0
jl ret
lea rdi, [rel tmp]
call _system ; this doesn't work
[...]
I noticed with a few more tests than system return 32512 which is if I well understand, 127. I tried to use sh -c 'my command' but it doesn't make any better thing ...
With dtruss, i found out that the call of posix_spawn fail, I don't know why, here is what I find for the 2 call _system of my sample :
PID/THRD RELATIVE ELAPSD CPU SYSCALL(args) = return
3040/0x143a1: 2271 243 240 posix_spawn(0x7FFEEFBFF454, 0x7FFF5BDBD256, 0x7FFEEFBFF360) = 0 0
3040/0x143a1: 2492 157 153 posix_spawn(0x7FFEEFBFF454, 0x7FFF5BDBD256, 0x7FFEEFBFF360) = -1 Err#14
I can't figure out why it doesn't work ! I can't find on the internet any specification about this function 'system'.
This question already has an answer here:
NASM issue on OSX 64-bit [duplicate]
(1 answer)
Closed 4 years ago.
I'm new to NASM and have struggle moving contents of variable from .data section to register. Following code outputs "Value: 0" instead of "Value: 1". If I write constant to register directly (mov qword rax, 25) everything works OK.
; /usr/local/bin/nasm -f macho64 sum.asm && ld -macosx_version_min 10.7.0 -lSystem -o sum sum.o && ./sum
section .data
myvar: dq 1234
message: db "Value: %i", 10, 0
.len: equ $ - message
global start
extern _printf
extern _exit
section .text
start:
default rel
; This outputs "Value: 0"
mov qword [myvar], 1
mov rax, [myvar]
; This works:
; mov qword rax, 25
; Output
mov rsi, rax
mov qword rax, 0
lea rdi, [rel message]
call _printf
mov qword rax, 0
call _exit
/usr/local/bin/nasm -v says:
NASM version 2.11.08 compiled on Mar 10 2015
The OS X NASM 2.11.08 bug strikes again. Use an older version (like 2.11.06), or a newer version with a fix for relative symbol addressing in the data section. Or use yasm.
Like I said in comments, you can zero a 64bit register with xor eax, eax. That's the standard idiom.
Writing to a 32bit reg always clears the upper32 of the 64bit register. This saves a lot of instruction bytes compared to moving a 64bit immediate.
mov qword rax, 25
Is still a 32bit immediate move. The qword is unnecessary. The instruction does have an unneeded REX prefix to make it a 64bit write, instead of just automatically clearing the high 32 by writing the low 32.
mov eax, 25
does the same thing, but with fewer instruction bytes.
Your code is correct, except for the global entry point main which is needed (but not required, you can adjust the entry point -- with link options). Here you are linking with the libc printf and exit functions. While compilers differ, using printf rather than _printf can help.
With only those semantic changes (and compiling on Linux instead of Mac), your code gives the desired output:
section .data
myvar: dq 1234
message: db "Value: %i", 10, 0
.len: equ $ - message
global main
extern printf
extern exit
section .text
main:
default rel
; This outputs "Value: 0"
mov qword [myvar], 1
mov rax, [myvar]
; Output
mov rsi, rax
mov qword rax, 0
lea rdi, [rel message]
call printf
mov qword rax, 0
call exit
Compile
$ nasm -felf64 -o obj/label64.o label64.asm
$ ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib64/crt1.o \
/usr/lib64/crti.o obj/label64.o /usr/lib64/crtn.o -lc -o bin/label64
Output
$ ./bin/label64
Value: 1
Note: you may need to adjust the paths needed by the link command. Otherwise, you can just call gcc and let it sort the paths out. E.g.:
$ gcc -o bin/label64 obj/label64.o
This is my first time programming in assembly for the Mac, and keep getting some strange errors that I haven't had much luck with googling-wise. So far, I'm just trying to print "Hello, World!" onto the terminal. Here is my code:
global _main
section .text
_main:
mov rax, 0x20000004
mov rdi, 1
mov rsi, msg
mov rdx, msg.len
syscall
mov rax, 0x20000001
mov rdi, 0
syscall
section .data
msg: db "Hello, World!", 10
.len: equ $ - msg
Whenever I run this code, I use the command nasm -f macho64 print.asm. By the way, nasm -v prints NASM version 2.11.08 compiled on Mar 10 2015. When I use the command above, NASM gives this output:
print.asm:9: fatal: No section for index 2 offset 0 found
I'm stumped and would like any help. Thanks!
I met the seemly problem. from the:
instead of :" mov rsi, msg", use: "lea rsi, [rel msg]"
I'm trying to write a simple helloworld in assembler 64 on Mac with NASM.
Every time I try to run it I'm getting this error:
Illegal instruction: 4
Here is my code:
section .text
global _main
_main:
mov rax, 4
mov rbx, 1
mov rcx, tekst
mov rdx, dlugosc
int 80h
mov rax, 1
int 80h
section .data
tekst db "Hello, world", 0ah
dlugosc equ $ - tekst
I'm compiling with:
nasm -f macho64 HelloWorld.asm
And I'm linking with:
ld -o HelloWorld -arch x86_64 -macosx_version_min 10.10 -lSystem -no_pie HelloWorld.o
Any help is highly appreciated.
Let's start with the most important thing:
On Mac OSX, system calls are preceded by an 0x2000###, so for an exit it would 0x2000001.
Next, we need to use the correct registers to pass arguments.
The number of the syscall has to be passed in register rax.
rdi - used to pass 1st argument to functions
rsi - used to pass 2nd argument to functions
rdx - used to pass 3rd argument to functions
rcx - used to pass 4th argument to functions
r8 - used to pass 5th argument to functions
r9 - used to pass 6th argument to functions
A system-call is done via the syscall instruction. The kernel destroys registers rcx and r11.
So bringing this together, a fixed version of your code is:
section .text
global _main
_main:
mov rax, 0x2000004
mov rdi, 1
mov rsi, tekst
mov rdx, dlugosc
syscall
mov rax, 0x2000001
syscall
section .data
tekst db "Hello, world", 0ah
dlugosc equ $ - tekst