I am making a calculator in assembly for practice. It is working fine except for when the answer is displayed, the new line character (0x0A) will not display. Instead there is a box with the numbers 0014 inside (Unicode probably). Am I doing something wrong?
bits 64 ; 64-bit (amd64) code
section .data
stdin: equ 0
stdout: equ 1
sys_read: equ 0
sys_write: equ 1
sys_exit: equ 60
l_out1: db "Simple Assembly Addition",0Ah,": "
l_len1: equ 27
l_out2: db ": "
l_len2: equ 2
l_out3: db "Answer is: "
l_len3: equ 11
section .bss
l_in1: resb 3 ; reserve 3 bytes (digits)
l_in2: resb 3 ; reserve 3 bytes (digits)
l_ans: resb 4 ; answer
section .text
global _start
_start:
mov rax,sys_write ; system call id
mov rdi,stdout ; descriptor
mov rsi,l_out1
mov rdx,l_len1
syscall
mov rax,sys_read ; system call id
mov rdi,stdin ; descriptor
mov rsi,l_in1
mov rdx,3 ; see .bss
syscall
mov rax,sys_write ; system call id
mov rdi,stdout ; descriptor
mov rsi,l_out2
mov rdx,l_len2
syscall
mov rax,sys_read ; system call id
mov rdi,stdin ; descriptor
mov rsi,l_in2
mov rdx,3
syscall
mov r8,[l_in1] ; copy l_in1 to rax
sub r8,"0"
mov r9,[l_in2] ; copy l_in2 to rax
sub r9,"0"
add r8,r9
add r8,"0" ; add 0 for ascii conversion
mov [l_ans],r8 ; store answer to address of l_ans
mov rax,sys_write ; system call id
mov rdi,stdout ; descriptor
mov rsi,l_out3
mov rdx,l_len3
syscall
mov rax,sys_write ; system call id
mov rdi,stdout ; descriptor
mov rsi,l_ans
mov rdx,4
syscall
mov rax,sys_write
mov rdi,stdout
mov rsi,0Ah
mov rdx,1
syscall
mov rax,sys_exit ; system call id
mov rdi,0 ; return 0
syscall
Related
I made this program that open a image file and find a hidden message in the file. I have to print the message on the console.
i think the part where i open the file and search for the hidden message is right, but i don´t know for sure because i can´t print the output to confirm.
this is the code:
; Example program to demonstrate file I/O.
; This example will open/create a file, write some
; information to the file, and close the file.
; Note, the file name is hard-coded for this example.
; This example program will open a file, read the
; contents, and write the contents to the screen.
; This routine also provides some very simple examples
; regarding handling various errors on system services.
; -------------------------------------------------------
section .data
; -----
; Define standard constants.
LF equ 10 ; line feed
NULL equ 0 ; end of string
TRUE equ 1
FALSE equ 0
EXIT_SUCCESS equ 0 ; success code
STDIN equ 0 ; standard input
STDOUT equ 1 ; standard output
STDERR equ 2 ; standard error
SYS_write equ 1; write
SYS_read equ 0 ; read
SYS_open equ 2 ; file open
SYS_close equ 3 ; file close
SYS_exit equ 60 ; terminate
SYS_creat equ 85 ; file open/create
SYS_time equ 201 ; get time
O_CREAT equ 0x40
O_TRUNC equ 0x200
O_APPEND equ 0x400
O_RDONLY equ 000000q ; read only
O_WRONLY equ 000001q ; write only
S_IRUSR equ 00400q
S_IWUSR equ 00200q
S_IXUSR equ 00100q
; -----
; Variables/constants for main.
BUFF_SIZE equ 256
newLine db LF, NULL
db LF, LF, NULL
fileName dq 6
fileDesc dq 0
errMsgOpen db "Error opening the file.", LF, NULL
errMsgRead db "Error reading from the file.", LF, NULL
offset db 1
size db 1
; -------------------------------------------------------
section .bss
readBuffer: resb BUFF_SIZE
; -------------------------------------------------------
section .text
global _start
_start:
xor rax, rax
xor rcx, rcx
xor rdx, rdx
xor rbx, rbx
mov rbx, rsp
mov rax, qword [rbx+16]
mov [fileName], rax
xor rax, rax
push rsp
; Attempt to open file - Use system service for file open
openInputFile:
pop rax ; pop argc value - should be 2
cmp rax, 0x2
jne done
mov rax, SYS_open ; file open
mov rdi, fileName ; file name string
mov rsi, O_RDONLY ; read only access
syscall ; call the kernel
cmp rax, 0 ; check for success
jl errorOnOpen
mov qword [fileDesc], rax ; save descriptor
; -----
; Read from file.
;
mov rax, SYS_read
mov rdi, qword [fileDesc]
mov rsi, readBuffer
mov rdx, BUFF_SIZE
syscall
cmp rax, 0
jl errorOnRead
; -----
; Print the buffer.
; add the NULL for the print string
mov rax, qword [readBuffer+2] ;SSSS
mov qword [size], rax
mov rax, qword [readBuffer+10] ;OOOO
mov [offset], rax
mov rcx, 0
ler: ;ler um caracter
mov rbp, 0
xor rbx, rbx
xor rdx, rdx
lerloop:
inc rax
cmp rax, [size]
je errorOnRead
saltaQuartobyte:
inc ecx
cmp ecx, 4
jne continua
inc rax ;incremneta rax outra vez para saltar o quarto
cmp rax, [size]
je errorOnRead
mov ecx, 0
continua:
mov bl, byte [readBuffer+rax]
shl rdx, 1
shr rbx, 1
adc rdx, 0
inc rbp
cmp rbp, 7 ;fim do caracter ASCII, 0X 0XXX XXXX
jne lerloop
mov rdi, rdx
call printString ; imprime caracter ASCII
cmp rax, [size] ;comea o priximo
jne ler
; -----
; Close the file.
mov rax, SYS_close
mov rdi, qword [fileDesc]
syscall
jmp done
; -----
; Error on open.
errorOnOpen:
mov rdi, errMsgOpen
call printString
jmp done
; Error on read.
errorOnRead:
mov rdi, errMsgRead
call printString
jmp done
; -----
; program done.
done:
mov rax, SYS_exit
mov rdi, EXIT_SUCCESS
syscall
; **********************************************************
; Generic procedure to display a string to the screen.
global printString
printString:
push rbp
mov rbp, rsp
push rbp
; -----
; Call OS to output string.
mov rax, SYS_write ; code for write()
mov rsi, rdi ; addr of characters
mov rdi, STDOUT ; file descriptor
; count set above
syscall ; system call
; -----
; String printed, return to calling routine.
prtDone:
pop rbx
pop rbp
ret
this is my last attempt of the print but the program still don't print anything, and I don't understand why? or what's wrong?
A fundamental error
push rsp
; Attempt to open file - Use system service for file open
openInputFile:
pop rax ; pop argc value - should be 2
cmp rax, 0x2
jne done
mov rax, SYS_open ; file open
Your program starts with copying the stackpointer RSP to the accumulator RAX, and then compares to see if the value is 2, but when is the stackpointer ever going to be 2? And so, the program will always prematurely exit. No wonder that nothing gets printed.
A selection of other errors
offset db 1
size db 1
...
mov rax, qword [readBuffer+2] ;SSSS
mov qword [size], rax
mov rax, qword [readBuffer+10] ;OOOO
mov [offset], rax
You have reserved not enough room to store the qwords size and offset!
Better store them in the .bss section using resq:
section .bss
readBuffer: resb BUFF_SIZE
offset resq 1
size resq 1
mov rax, qword [readBuffer+2] ;SSSS
mov qword [size], rax
mov rax, qword [readBuffer+10] ;OOOO
mov [offset], rax
If the file is a .BMP (I'm considering those well-known offsets), then the size and offset fields are actually dwords. You would have to write instead (loading EAX automatically zero extends the value into RAX):
mov eax, [readBuffer+2] ;SSSS
mov [size], rax
mov eax, [readBuffer+10] ;OOOO
mov [offset], rax
printString:
push rbp
mov rbp, rsp
push rbp <<<<
...
pop rbx <<<<
pop rbp
ret
Because of the mismatch, you're destroying RBX on return.
The code that you used depends on calculating the length of the ASCIIZ string. You cannot just leave that out!
This is my code with commented explanations:
SECTION .data ; Section containing initialised data
EatMsg: db "Eat at Joe's!",10
EatLen: equ $-EatMsg
SECTION .bss ; Section containing uninitialized data
SECTION .text ; Section containing code
global _start ; Linker needs this to find the entry point!
_start:
nop ; This no-op keeps gdb happy...
mov rax,1 ; Code for Sys_write call
mov rdi, 1 ; Specify File Descriptor 1: Standard Output
mov rsi, EatMsg ; Pass offset of the message
mov rdx, EatLen ; Pass the length of the message
mov R9, [EatMsg] ; move the adresse of Msg into R9
syscall
mov rcx, 5
DoMore:
mov rax, 1 ; Code for Sys_write call
mov rdi, 1 ; Specify File Descriptor 1: Standard Output
mov rsi, EatMsg ; Pass offset of the message
mov rdx, EatLen ; Pass the length of the message
dec rcx
jnz DoMore
syscall ; Make kernel call
mov rax, 1 ; Code for exit
mov rdi, 0 ; Return a code of zero
syscall ; Make kernel call
I'm still learning assembly so my question may be trivial.
I'm trying to write an echo program with syscall, in which I get a user input and give it as output on the next line.
section .text
global _start
_start:
mov rax,0
mov rdx, 13
syscall
mov rsi, rax
mov rdx, 13
mov rax, 1
syscall
mov rax, 60
mov rdi, 0
syscall
I'm assuming all you want to do is return the input to the output stream, so to do that you need to do a few things.
First, create a section .bss in your code. This is for initializing data. You will initialize a string with any name you want and do so with label resb sizeInBits. for demonstration it will be a 32 bit string called echo.
Extra note, the ';' character is used for comments similar to what // is in c++.
Example code
section .data
text db "Please enter something: " ;This is 24 characters long.
section .bss
echo resb 32 ;Reserve 32 bits (4 bytes) into string
section .text
global _start
_start:
call _printText
call _getInput
call _printInput
mov rax, 60 ;Exit code
mov rdi, 0 ;Exit with code 0
syscall
_getInput:
mov rax, 0 ;Set ID flag to SYS_READ
mov rdi, 0 ;Set first argument to standard input
; SYS_READ works as such
;SYS_READ(fileDescriptor, buffer, count)
;File descriptors are: 0 -> standard input, 1 -> standard output, 2 -> standard error
;The buffer is the location of the string to write
;And the count is how long the string is
mov rsi, echo ;Store the value of echo in rsi
mov rdx, 32 ;Due to echo being 32 bits, set rdx to 32.
syscall
ret ;Return to _start
_printText:
mov rax, 1
mov rdi, 1
mov rsi, text ;Set rsi to text so that it can display it.
mov rdx, 24 ;The length of text is 24 characters, and 24 bits.
syscall
ret ;Return to _start
_printInput:
mov rax, 1
mov rdi, 1
mov rsi, echo ;Set rsi to the value of echo
mov rdx, 32 ;Set rdx to 32 because echo reserved 32 bits
syscall
ret ;Return to _start
I'm trying to get information about file permissions. I am using the sys_access system call. Here is my code snippet:
mov eax, 33
mov ebx, fileName
mov ecx, 1
int 80h
cmp eax, 0
jl .error
If eax is -1 there is an error, and I am not getting one, but I need to check all the permissions of the file (owner, group, others). How do I do that?
You can use the kernel function sys_newstat (No. 106 - look at this table) to get the file permissions. The structure stat is a never ending horror, but the following example works at least on my Debian Wheezy 64 bit (NASM, 32-bit and 64-bit modes):
SECTION .data
filename db '/root' ; Just an example, can be replaced with any name
filename_len equ $ - filename ; Length of filename
db 0 ; Terminator for `Int 80h / EAX = 106`
perm_out db 'Permissions: '
perm db 'drwxrwxrwx'
perm_len equ $ - perm ; Index of last character in `perm`
lf db 10
perm_out_len equ $ - perm_out ; Length of `Permissions: ...\n`
SECTION .bss
stat resb 256 ; Way too much, but size is variable depending on OS
SECTION .text
global _start
_start:
mov eax,4 ; sys-out
mov edx,filename_len ; length of string to print
mov ecx,filename ; Pointer to string
mov ebx,1 ; StdOut
int 0x80 ; Call kernel
mov eax,4 ; sys-out
mov edx,1 ; Length of string to print
mov ecx, lf ; Pointer to string
mov ebx,1 ; StdOut
int 0x80 ; Call kernel
mov eax, 106 ; sys_newstat
mov ebx, filename ; Pointer to ASCIIZ file-name
mov ecx, stat ; Pointer to structure stat
int 80h
test eax, eax
jz .noerr
mov eax,1 ; sys_exit
mov ebx,1 ; Exit code, 1=not normal
int 0x80 ; Call kernel
.noerr:
movzx eax, word [stat + 8] ; st_mode (/usr/include/asm/stat.h)
mov ebx, perm_len
; rwx bits
mov ecx, 9
.L1:
sub ebx, 1
shr eax, 1
jc .J1
mov byte [perm + ebx], '-'
.J1:
loop .L1
; directory bit
sub ebx, 1
shr eax, 6
jc .J2
mov byte [perm + ebx], '-'
.J2:
mov eax,4 ; sys-out
mov edx,perm_out_len ; Length of string to print
mov ecx,perm_out ; Pointer to string
mov ebx,1 ; StdOut
int 0x80 ; Call kernel
mov eax,1 ; sys_exit
mov ebx,0 ; Exit code, 0=normal
int 0x80 ; Call kernel
I have a NASM program for 64bit Linux system which works with standard I/O devices and it looks something like that:
section .data
prompt db "Enter your text: ", 10
length equ $ - prompt
text times 255 db 0
textSize equ $ - text
section .text
global main
main:
mov rax, 1
mov rdi, 1
mov rsi, prompt
mov rdx, length
syscall ;print prompt
mov rax, 0
mov rdi, 0
mov rsi, text
mov rdx, textSize
syscall ;read text input from keyboard
mov rcx, rax ; rcx - character counter
mov rsi, text ; a pointer to the current character starting from the beginning.
****
exit:
mov rax, 60
mov rdi, 0
syscall
I need the program to read from and write to the files, but I can't find anywhere which syscalls has to be used and how they should be used to achieve these results. So, I am wondering if someone of you could help me. Thanks in advance.
Use system calls "open" and "close":
Open a file under 64-bit Linux:
rax = 2
rdi = pointer to NUL-terminated filename
rsi = something like O_WRONLY
rdx = file flags if creating a file (e.g. 0644 = rw-r--r--)
syscall
now rax contains the file hanle
Close a file:
rax = 3
rdi = file handle
syscall
Reading/writing from/to a file:
rax = 0 or 1 (like keyboard/screen in/output)
rdi = file handle (instead of 0/1)
...
;this program is only overwrite the result.txt
;to write it on bottom you need to lseek to the end
section .data
prompt db "Enter your text: ",10
length equ $ - prompt
text times 255 db 0
textsize equ $-text
fname db "result.txt",0
fd dq 0
thefox dq 0
global _start
section .text
_start:
mov al,1
mov dil,al
mov esi,prompt
mov dl,length
syscall
mov al,0
mov dil,al
mov rsi,text
mov rdx,textsize
syscall
mov [thefox],rax
mov rax,2
mov rdi,fname
mov rsi,0102o
mov rdx,0666o
syscall
mov [fd],rax
mov rdx,[thefox]
mov rsi,text
mov rdi,[fd]
mov rax,1
syscall
mov rdi,[fd]
mov rax,3
syscall
mov rax,60
syscall