I want to get a basic feel for assembly and wrote a program that ought to
displays the string Enter a number:
reads in user input
counts the number read down to 0 and prints the number in each iteration in a loop.
Here is my code.
section .data
msg db 'Enter a number:'
len equ $ - msg
section .bss
num resb 1
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax,4 ;sys_write
mov ebx,1
mov ecx,msg ;the message "Enter a number:"
mov edx,len ;write "enter a number" on the screen
int 80h
mov eax,3 ;reading in user input into num
mov ebx,2
mov ecx,num
mov edx,1
int 80h
mov ecx,num
jmp loop1
mov eax,1 ;system call number (sys_exit)
int 80h ;call kernel
loop1:
mov edx,1
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 80h
loop loop1
mov eax,1
int 80h
When entering loop1 nothing is written to the terminal instead of the countdown I want. Can someone tell me what I fail to see?
Related
I am trying to write a program that accepts 2 digits as user input, and then outputs their sum. I keep getting segmentation error when trying to run program(I am able to input 2 digits, but then the program crashes). I already check answers to similar questions and many of them pointed out to clear the registers, which I did, but I am still getting a segmentation fault.
section .text
global _main ;must be declared for linker (ld)
default rel
_main: ;tells linker entry point
call _readData
call _readData1
call _addData
call _displayData
mov RAX, 0x02000001 ;system call number (sys_exit)
syscall
_addData:
mov byte [sum], 0 ; init sum with 0
lea EAX, [buffer] ; load value from buffer to register
lea EBX, [buffer1] ; load value from buffer1 to register
sub byte [EAX], '0' ; transfrom to digit
sub byte [EBX], '0' ; transform to digit
add [sum], EAX ; increment value of sum by value from register
add [sum], EBX ; increment value of sum by value from 2nd register
add byte [sum], '0' ; convert to ASCI
xor EAX, EAX ; clear registers
xor EBX, EBX ; clear registers
ret
_readData:
mov RAX, 0x02000003
mov RDI, 2
mov RSI, buffer
mov RDX, SIZE
syscall
ret
_readData1:
mov RAX, 0x02000003
mov RDI, 2
mov RSI, buffer1
mov RDX, SIZE
syscall
ret
_displayData:
mov RAX, 0x02000004
mov RDI, 1
mov RSI, sum
mov RDX, SIZE
syscall
ret
section .bss
SIZE equ 4
buffer: resb SIZE
buffer1: resb SIZE
sum: resb SIZE
I see that, unlike other languages I learned, it is quite difficult to find a good source /tutorial about programming assembly using nasm on x86_64 architecture. Is there any kind of walkthrough for beginners(so I do not need to ask on SO everytime I am stuck :D)
So I have this code here were I'm trying to add two numbers in it but I can't seem to get the output from this code that I've been trying do for a while. :
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov edx, '6'
sub edx,'0'
mov ecx ,'7'
sub ecx,'0'
add edx,ecx
mov [math_sum], edx
mov eax,msg
mov ebx, len
mov ecx,1
mov edx,4
int 0x80
mov eax,math_sum
mov ebx,1
mov ecx,1
mov edx,4
int 0x80
mov edx,1
int 0x80
section .data
msg db "Sum of 6 and 7 is:"
len equ $ - msg
segment .bss
math_sum resb 2
I'm getting Segmentation fault but I don't know how to fix it.
I've searched around and I haven't found anything.
The code is as follows:
hello_world db "Hello World!",10
.hellolen equ $ - hello_world
get_input db "Enter a number: ",10
.getlen equ $ - get_input
input times 10 db 0
.len equ $ - input
section .text
global start
; Arguments go in the registers
;RDI, RSI, RDX, R10, R8, and R9, in order.
;System call number goes into RAX.
start:
call printHello
call askInput
call takeInput
call printInput
call exit
ret
printHello:
mov rax, 0x2000004
mov rdi, 1
mov rsi, hello_world
mov rdx, hello_world.hellolen
syscall
askInput:
mov rax, 0x2000004 ; System call write = 4
mov rdi, 1 ; Write to standard out = 1
mov rsi, get_input ; The address of enter string
mov rdx, get_input.getlen ; The size to write
syscall
takeInput:
mov rax, 0x2000003 ; System call read = 3
mov rdi, 2 ;
mov rsi, input ; buffer that we are reading to
mov rdx, input.len ;to create buffer overflow
;we can input more than
;input.len
syscall
printInput:
mov rax, 0x2000004 ; System call write = 4
mov rdi, 1 ; Write to standard out = 1
mov rsi, input ; The address of enter string
mov rdx, input.len ; The size to write
syscall
exit:
mov rax, 0x2000001 ; System call number for exit = 1
mov rdi, 0 ; Exit success = 0
syscall ; Invoke the kernel
And the output:
Hello World!
Enter a number:
r: <- weird random r:
test <- input by me
test <- correct value returned
Is there a way to view this with GDB so that I may figure out what is causing this problem? I'm not sure how to approach this from a troubleshooting perspective. Thank you!
I edited the code according to commentary and I am still getting the same odd r: in the output.
I need help. I'm trying to run the program (NASM) below in SASM.
SYS_EXIT equ 1
SYS_READ equ 3
SYS_WRITE equ 4
STDIN equ 0
STDOUT equ 1
segment .data
msg1 db "Enter a digit ", 0xA,0xD
len1 equ $- msg1
msg2 db "Please enter a second digit", 0xA,0xD
len2 equ $- msg2
msg3 db "The sum is: "
len3 equ $- msg3
segment .bss
num1 resb 2
num2 resb 2
res resb 1
section .text
global _start ;must be declared for using gcc
_start: ;tell linker entry point
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num1
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 0x80
mov eax, SYS_READ
mov ebx, STDIN
mov ecx, num2
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 0x80
; moving the first number to eax register and second number to ebx
; and subtracting ascii '0' to convert it into a decimal number
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
; add eax and ebx
add eax, ebx
; add '0' to to convert the sum from decimal to ASCII
add eax, '0'
; storing the sum in memory location res
mov [res], eax
; print the sum
mov eax, SYS_WRITE
mov ebx, STDOUT
mov ecx, res
mov edx, 1
int 0x80
exit:
mov eax, SYS_EXIT
xor ebx, ebx
int 0x80
I had this error:
[20:53:11] Warning! Errors have occurred in the build:
c:/program files (x86)/sasm/mingw/bin/../lib/gcc/mingw32/4.6.2/../../../libmingw32.a(main.o): In function 'main':
C:\MinGW\msys\1.0\src\mingwrt/../mingw/main.c:73: undefined reference to `WinMain#16'
Also, how do I limit users input up to 4 digits only?
global _start should change to global main and Linux system calls should be replaced by Windows API function calls and declared as external. Modern versions of Windows doesn't approve use of system calls due to malware or badware risks, so deprecated (permanent) system call codes. Every modern version of Windows has different system call number codes, though you can find them on internet, you shouldn't rely on them unless you want to revise your assembly code for each version of Windows thus reducing portability and increasing workload. There are significant differences between Linux/Mac and Windows in the way of handling registers, stack and function names.
As the title suggest I seem to be having a hard time converting the below code to do the exact same thing, which is to read from stdin and stdout. My professor wants us to stop using int 80h and switch over to using gcc. I've had no problems with reading input with the below code however, switching over to gcc is where I start getting segmentation core dump errors.
section .bss
buf resb 1 ; 1000-byte buffer (in data section)
section .text
global _start
_start:
loop1: mov edx, 1 ; max length
mov ecx, buf ; buffer
mov ebx, 0 ; stdin
mov eax, 3 ; sys_read
int 80h
cmp eax, 0 ; end loop if read <= 0
jle lpend1
mov edx, eax ; length
mov ecx, buf ; buffer
mov ebx, 1 ; stdout
mov eax, 4 ; sys_write
int 80h
jmp loop1 ; go back for more
lpend1:
mov eax, 1
mov ebx, 0
int 80h
My attempt at converting the above to perform the same task
SECTION .data
format: db "%c",0
SECTION .bss
buff: resb 1
SECTION .text
extern printf
extern scanf
global main
main:
loop1:
push buff ;buff will hold the characters in the string/file
push format ;expect character for every buff
call scanf
add esp, 8 ;clear stack
cmp eax, 0 ;if eax is equal to 0 then EOF
je lpend1 ;jump to end main func
xor eax, eax ;clear eax
mov eax, buff ;mov buff to eax register
push eax ;push eax onto the stack
mov eax, format ;mov the string format to eax
push eax ;push onto the stack
call printf ;call printf, prints to screen
add esp, 8 ;clear the stack
jmp loop1 ;jump back to top and repeat
lpend1:
ret ;end of main