I'm writing a simple assembly program on Darwin x86_64 (MacOS 10.14.6) that creates a file (test.txt) and writes "E" to it. However, for some reason, the "E" is not written to the file. What am I doing wrong?
Here's my program:
global start
section .text
start:
;Create the file
mov rax, 0x2000005
mov rdi, fname
mov rsi, 0x200
mov rdx, 0o644
syscall
;Write to file
mov rdi, rax ;As far as I know, this uses the fd returned by creating a file (previous syscall)
mov rsi, msg
mov rdx, 1
mov rax, 0x2000004
syscall
;Exit
mov rax, 0x2000001
mov rdi, 0
syscall
section .data
msg: db "E" ;Message
fname: db "test.txt" ;File name
I have also tried this:
global start
section .text
start:
mov rax, 0x2000005
mov rdi, fname
mov rsi, 0x200
mov rdx, 0o644
syscall
mov rdi, rax
mov rsi, msg
mov rdx, 2
mov rax, 0x2000004
syscall
mov rax, 0x2000001
mov rdi, 0
syscall
section .data
msg: db "E", -1
fname: db "test.txt", 0
Yet neither work.
I found the answer:
I found that opening the file with create mode and write mode works.
global start
section .text
start:
;Open file with create mode and write mode
mov rax, 0x2000005
mov rdi, fname
mov rsi, 0x201
mov rdx, 0o644
syscall
;Now write
mov rdi, rax
mov rsi, msg
mov rdx, 1
mov rax, 0x2000004
syscall
;Exit
mov rax, 0x2000001
mov rdi, 0
syscall
section .data
msg: db "E"
fname: db "test.txt"
Also, here is an array of flags for opening files:
O_ACCMODE: 0x3
O_APPEND: 0x8
O_ASYNC: 0x40
O_CLOEXEC: 0x1000000
O_CREAT: 0x200
O_DIRECTORY: 0x100000
O_DSYNC: 0x400000
O_EXCL: 0x800
O_EXLOCK: 0x20
O_NDELAY: 0x4
O_NOCTTY: 0x20000
O_NOFOLLOW: 0x100
O_NONBLOCK: 0x4
O_RDONLY: 0x0
O_RDWR: 0x2
O_SHLOCK: 0x10
O_SYNC: 0x80
O_TRUNC: 0x400
O_WRONLY: 0x1
To combine, use the | operator (in C) or or (in assembly).
Related
The assembly file is obtained by using gcc -g -S, and the part of .s file is as follows:
.L3:
.loc 1 22 11
mov eax, DWORD PTR -12[rbp]
mov edx, eax
mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
call _ZNSolsEi
.loc 1 22 18
mov rdx, QWORD PTR .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_[rip]
mov rcx, rax
call _ZNSolsEPFRSoS_E
.loc 1 23 7
mov DWORD PTR -12[rbp], 0
.loc 1 12 2
add DWORD PTR -4[rbp], 1
jmp .L6
What does .loc 1 22 11 stand for?
When the -g flag is added to gcc it directs the compiler to add debugging information. .loc appears only when the compiler generates debugging information with -g flag:
https://sourceware.org/binutils/docs-2.38/as/Loc.html#Loc
Recently I have been trying to learn assembly x86 using NASM on a Windows platform, I am trying to make a function that reads a character from stdin ignoring any line feeds and carriage returns, but the problem is that when the function reaches the ret operation the program crashes, strangely when i run the function without the call to ReadConsoleA
the program finishes correctly.
Code:
section .bss
temp_char resb 1
bytes_written_holder resq 1
section .data
global _start
extern GetStdHandle, WriteConsoleA, ReadConsoleA, ExitProcess
section .text
getinput:
mov rcx, -10
call GetStdHandle
mov rcx, rax
mov rdx, temp_char
mov r8, 1
mov r9, bytes_written_holder
push 0
call ReadConsoleA
mov al, [temp_char]
cmp al, 0xa
je getinput
cmp al, 0xd
je getinput
ret
_start:
call getinput
mov rcx, -11
call GetStdHandle
mov rcx, rax
mov rdx, temp_char
mov r8, 1
mov r9, bytes_written_holder
push 0
call WriteConsoleA
mov rcx, 0
call ExitProcess
I am using NASM to assemble and GoLink to link:
nasm -f win64 printtest.s -o printtest.obj
GoLink.exe /console /entry _start printtest.obj kernel32.dll
I just encountered a weird issue with gdb, though I'm not sure, if I'm missing something.
Let's suppose I have these two files:
somefile.asm:
01 section .text
02
03 funca:
04 mov eax, 5
05 mov ebx, 5
06 cmp eax, ebx
07 je aisequal
08 mov ecx, 13
09 mov edx, 19
10 ret
11
12 aisequal:
13 mov ecx, 17
14 mov edx, 21
15 ret
and
somefile_test.asm:
01 %include "somefile.asm"
02
03 section .text
04 global _start
05
06 _start:
07 xor eax, eax
08 xor ebx, ebx
09 xor ecx, ecx
10 xor edx, edx
11 call funca
12
13 mov eax, 1
14 mov ebx, 0
15 int 0x80
I compile and link it using
nasm -f elf -g -F dwarf somefile_test.asm
ld -m elf_i386 -o somefile_test.out somefile_test.o
And then debug my application using gdb:
gdb somefile_test.out
I now set a breakpoint in the imported file:
GNU gdb (GDB) 10.1
(gdb) b somefile.asm:5
Breakpoint 1 at 0x8049000: file somefile.asm, line 5.
(gdb) r
Starting program: /<bla>/somefile_test.out
Breakpoint , funca () at somefile.asm:5
5 mov ebx, 5
Now appearantly, the execution stopped at the correct position. The next line to be executed would be 5, which is mov ebx, 5.
However, the last line should've been mov eax, 5 which should have already been executed. It was not:
(gdb) i r eax
eax 0x0 0
It gets even weirder:
(gdb) si
6 cmp eax, ebx
(gdb) i r eax ebx
eax 0x5 5
ebx 0x0 0
Now, eax is set, but ebx is not (yet).
If I execute the next line, it is set:
(gdb) si
7 je aisequal
(gdb) i r eax ebx
eax 0x5 5
ebx 0x5 5
However, I'd expect the program to jump to line 12 (aisequal) now, but it doesn't:
(gdb) si
8 mov ecx, 13
On the next instruction, it suddenly goes to the right line:
(gdb) si
14 mov edx, 21
(gdb) i r eax ebx edx
eax 0x5 5
ebx 0x5 5
edx 0x0 0
And so on:
(gdb) si
15 ret
(gdb) i r eax ebx ecx edx
eax 0x5 5
ebx 0x5 5
ecx 0x11 17
edx 0x0 0
If I put all my code in a single file, everything works as expected:
01 section .text
02 global _start
03
04 _start:
05 xor eax, eax
06 xor ebx, ebx
07 xor ecx, ecx
08 xor edx, edx
09 call funca
10
11 mov eax, 1
12 mov ebx, 0
13 int 0x80
14
15 funca:
16 mov eax, 5
17 mov ebx, 5
18 cmp eax, ebx
19 je aisequal
20 mov ecx, 13
21 mov edx, 19
22 ret
23
24 aisequal:
25 mov ecx, 17
26 mov edx, 21
27 ret
GBU gdb (GDB) 10.1
(gdb) b 16
Breakpoint 1 at 0x8049019: file singlefile.asm, line 16.
(gdb) r
Starting program: /<bla>/singlefile.out
Breakpoint 1, funca () at singlefile.asm:16
16 mov eax, 5
(gdb) i r eax ebx ecx edx
eax 0x0 0
ebx 0x0 0
ecx 0x0 0
edx 0x0 0
(gdb) si
17 mov ebx, 5
(gdb) i r eax ebx ecx edx
eax 0x5 5
ebx 0x0 0
ecx 0x0 0
edx 0x0 0
(gdb) si
18 cmp eax, ebx
(gdb) si
19 je aisequal
(gdb) si
25 mov ecx, 17
(gdb) si
26 mov edx, 21
(gdb) i r eax ebx ecx edx
eax 0x5 5
ebx 0x5 5
ecx 0x11 17
edx 0x0 0
(gdb) si
aisequal () at singlefile.asm:27
27 ret
(gdb) i r eax ebx ecx edx
eax 0x5 5
ebx 0x5 5
ecx 0x11 17
edx 0x15 21
(gdb) si
_start () at singlefile.asm:11
11 mov eax, 1
Now I've only picked up gdb two days ago, so I'm not that familiar with it.
Can someone explain to me what's happening?
Is this a bug or am I missing something?
I am using
nasm 2.15.05-1
binutils 2.35.1-1
gdb 10.1-4
gcc 10.2.0-4
on Linux 5.9.14-arch1-1 #1 SMP PREEMPT Sat, 12 Dec 2020 14:37:12 +0000 x86_64 GNU/Linux
This looks like a bug in nasm. It didn't reproduce for me using nasm-2.14.
GDB will only display source info that the compiler/assembler tells it. If the assembler puts out incorrect info, then GDB will display that incorrect info and can't do anything about it.
To verify that the problem is in nasm, run objdump -dS somefile_test.o and compare the assembly and source listing. If they are also off by one, it's a bug in nasm.
Here is what I see:
somefile_test.o: file format elf32-i386
Disassembly of section .text:
00000000 <funca>:
section .text
funca:
mov eax, 5
0: b8 05 00 00 00 mov $0x5,%eax
mov ebx, 5
5: bb 05 00 00 00 mov $0x5,%ebx
cmp eax, ebx
a: 39 d8 cmp %ebx,%eax
je aisequal
c: 74 0b je 19 <aisequal>
Note how instructions and source perfectly line up.
Apparently, this is a regression in nasm.
Reported it to them.
I recently started programming in assembly language and could get something wrong. This code is supposed to write out "21947392":
section .data
nl db 10
section .bss
number resb 19
.end resb 1
section .text
GLOBAL start
start:
mov rdi, 21947392
call _printNumber
mov rax, 0x2000001
xor rdi, rdi
syscall
_printNumber:
mov rcx, 10
mov rsi, number.end
mov rax, rdi
_loop:
xor rdx, rdx
div rcx
add rdx, 48
mov [rsi], rdx
dec rsi
cmp rax, 0
jne _loop
mov rdi, rsi
inc rdi
mov rsi, number.end
sub rsi, rdi
call _print
mov rdi, nl
mov rsi, 1
call _print
ret
_print:
mov rax, 0x2000004
mov rdx, rsi
mov rsi, rdi
mov rdi, 1
syscall
ret
It is written for macOS x64 on NASM and it only prints "2" (and seems to even differ from one assembly to another)...
Here are the commands I use in terminal:
nasm -f macho64 -o printNumber.o printNumber.asm
ld printNumber.o -o printNumber
./printNumber
Please, help find what's wrong.
In this application, I am trying to print a character passed through command line arguments (Intel Mac OS X). EX:
./thisapp q
Desired output:
q
However, it prints out a bunch of symbols and nonsense, but what is interesting is that different characters produce different gibberish. This leads me to believe that I am close. Does this need to be "formatted" for it to produce the correct letter?
.section __DATA,__data
.section __TEXT,__text
.globl _start
_start:
push %rbp
mov %rsp,%rbp
lea -32(%rsp), %r10 #<--- should be argv
add $8, %r10 #<--- should be argv[1]
movl $0x2000004, %eax
mov $1, %edi
mov %r10, %rsi
mov $16, %edx
syscall
xor %rax, %rax
mov $0x2000001, %eax
mov $0, %edi
syscall
Thanks to everyone's help I was able to get this working. Here is the code in the event someone else is looking to do this:
.section __DATA,__data
.section __TEXT,__text
.globl _start
_start:
push %rbp
mov %rsp,%rbp
lea 24(%rbp), %r10
movl $0x2000004, %eax
mov $1, %edi
mov (%r10), %rsi
mov $1, %edx
syscall
xor %rax, %rax
mov $0x2000001, %eax
mov $0, %edi
syscall
I would like to point out that this will only print 1 element (letter/number). I still need to figure out how to get the length(size?) of whatever was passed.