Segmentation-fault error happening with Assembly code program - linux

I keep getting a segmentation fault error when running my code. Everything has compiled well, but I can't seem to get it to do what I want. The program is to ask the user to enter 3 integers, then ask the user what they think the average of the numbers would be, take that into account and then come back with whether or not the user guessed correctly
segment .data
;
; Output strings
;
prompt1 db "Enter a positive integer: ", 0
prompt2 db "Enter a second positive integer: ", 0
prompt3 db "Enter a third positive integer: ", 0
prompt4 db "Enter a guess of their average: ", 0
outmsg1 db "You entered ", 0
outmsg2 db " and ", 0
outmsg3 db " and ", 0
outmsg4 db "You guessed that the average is ", 0
outmsg5 db "You did you guess correctly? (0 = no, 1 = yes)", 0
avermsg db "The average of the numbers is ", 0
segment .bss
input1 resd 1
input2 resd 1
input3 resd 1
input4 resd 1
guess resd 1
segment .text
Global main
main:
enter 0,0 ; setup routine
pusha
mov eax, prompt1 ; print out prompt1
call print_string
call read_int ; read integer
mov [input1], eax ; store integer into input1
mov eax, prompt2 ; print out prompt2
call print_string
call read_int ; read integer
mov [input2], eax ; store integer into input2
mov eax, prompt3 ; print out prompt3
call print_string
call read_int ; read integer
mov [input3], eax ; store integer into input3
mov eax, prompt4 ; print out prompt4
call print_string
call read_int ; read integer
mov [guess], eax
mov eax, [input1] ; eax = dword at input1
add eax, [input2] ; eax += dword at input2
add eax, [input3] ; eax += dword at input3
mov ebx, 3
div ebx ; divides the sum by 3
mov ecx, eax ; freeing up eax, puts quotient into ecx
dump_regs 1 ; print out register values
; next print out results
mov eax, outmsg1
call print_string ; print out first message
mov eax, [input1]
call print_int
mov eax, outmsg2
call print_string ; print out second message
mov eax, [input2]
call print_int
mov eax, outmsg3
call print_string ; print out thrid message
mov eax, [input3]
call print_int
mov eax, outmsg4
call print_string ; print out fourth message
mov eax, [input4]
call print_int
xor ebx, ebx
cmp ecx, [guess]
sete bl
neg ebx
mov edx, ebx
and ecx, edx
not ebx
and ebx, [guess]
or edx, ebx
mov eax, outmsg5
call print_string
mov ecx, eax
call print_int
mov eax, [avermsg]
call print_string ; print out final message
mov ecx, edx
call print_int ; print out average of ebx
call print_nl ; print new line
popa
mov eax, 0 ; return back to C
leave
ret

It is not easy to pinpoint the problem without knowing the compiler you use.
Segmentation fault hapens in protected mode, when you try to access a segment you have no permissions to access.
You declare 3 diferent segments here. You have to make sure your ds register is initialized to your .data segment, before calling print_string.
It also seems problematic that after read_int you save the data to the input1 variable which seems to be in a different segment than that you used for printing the message, but you do not change ds.
I'm not familiar how exactly your compiler handles these segments, so please give a link to its documentation.

div ebx
the problem seems to be here. You have to zero out edx since is is the high order word of the divisor, so probably you're getting something like a division overflow exception.
If this isn't the case probably the problem is in some of your I/O routines

Related

Incorrect console output after previous output

Task: output the number in hexadecimal form to the console. After that print some string (let it be "String after num").
The first part is successful, but the second is not.
The input number is stored in memory by the num label.
String is stored in memory by the line label.
String length - lines.
Code:
global _start
section .data
num db 01111110b
temp db 0
line db 10, "String after num", 10
lines equ $-line
section .text
_start:
call write_hex ; write num in hex format
mov eax, 4 ; write "Hello world!"
mov ebx, 1 ;
mov ecx, line ;
mov edx, lines ;
int 80H ;
mov eax, 1 ; exit
xor ebx, ebx
int 80H
write_hex:
mov eax, [num]
mov [temp], eax
shr byte [num], 4
call to_hex_digit
call write_digit
mov eax, [temp]
mov [num], eax
and byte [num], 1111b
call to_hex_digit
call write_digit
ret
to_hex_digit:
add [num], byte '0'
cmp [num], byte '9'
jle end
add [num], byte 7
end: ret
write_digit:
mov eax, 4
mov ebx, 1
mov ecx, num
mov edx, 1
int 80H
ret
Output:
Thanks for any help.
I used an invalid register to store a temporary value. I replaced the register which will work with the temp from eax to al. See Jester's answer.

Assembly NASM x86 - Simple Stack Project

I'm writing a subroutine to simply reprint decimal numbers as strings using the stack, but not getting the values I expected. When I run it through the debugger I see that I can't get the value from esi into al. I suspect that I'm not allowed to use esi in the manner that I am, but I'm not sure on another way I can do this. Also, I am not allowed to push the elements I'm storing in edx onto the stack.
Subroutine code:
%define STDIN 0
%define STDOUT 1
%define SYSCALL_EXIT 1
%define SYSCALL_READ 3
%define SYSCALL_WRITE 4
%define BUFLEN 256
SECTION .bss ; uninitialized data section
src_str: resb BUFLEN ; buffer for backwards number
dec_str: resb BUFLEN ; number will be converted and put in this buffer
rlen: resb 4 ; length
SECTION .text ; code begins here
global prt_dec
; Begin subroutine
prt_dec:
push eax
push ebx
push ecx
push edx
push esi
push edi
mov eax, [esp + 28] ; store the decimal number 4 bytes each for each push, plus the eip
mov esi, src_str ; point esi to the backwards string buffer
mov edi, dec_str ; point edi to the new buffer
mov ebx, 10 ; stores the constant 10 in ebx
div_loop:
mov edx, 0 ; clear out edx
div ebx ; divide the number by 10
add edx, '0' ; convert from decimal to char
mov [esi], edx ; store char in output buffer
inc esi ; move to next spot in output buffer
inc ecx ; keep track of how many chars are added
cmp eax, 0 ; is there anything left to divide into?
jne div_loop ; if so, continue the loop
output_loop:
add esi, ecx ; move 1 element beyond the end of the buffer
mov al, [esi - 1] ; move the last element in the buffer into al
mov [edi], al ; move it into the first position of the converted output buffer
inc edi ; move to the next position of the converted output buffer
dec ecx ; decrement to move backwards through the output buffer
cmp ecx, 0 ; if it doesn't equal 0, continue loop
jne output_loop
print:
mov eax, SYSCALL_WRITE ; write out string
mov ebx, STDOUT
mov ecx, dec_str
mov edx, 0
mov edx, rlen
int 080h
pop_end:
pop edi ; move the saved values back into their original registers
pop esi
pop edx
pop ecx
pop ebx
pop eax
ret
; End subroutine
Driver:
%define STDIN 0
%define STDOUT 1
%define SYSCALL_EXIT 1
%define SYSCALL_READ 3
%define SYSCALL_WRITE 4
SECTION .data ; initialized data section
lf: db 10 ; just a linefeed
msg1: db " plus "
len1 equ $ - msg1
msg2: db " minus "
len2 equ $ - msg2
msg3: db " equals "
len3 equ $ - msg3
SECTION .text ; Code section.
global _start ; let loader see entry point
extern prt_dec
_start:
mov ebx, 17
mov edx, 214123
mov edi, 2223187809
mov ebp, 1555544444
push dword 24
call prt_dec
add esp, 4
call prt_lf
push dword 0xFFFFFFFF
call prt_dec
add esp, 4
call prt_lf
push 3413151
call prt_dec
add esp, 4
call prt_lf
push ebx
call prt_dec
add esp, 4
call prt_lf
push edx
call prt_dec
add esp, 4
call prt_lf
push edi
call prt_dec
add esp, 4
call prt_lf
push ebp
call prt_dec
add esp, 4
call prt_lf
push 2
call prt_dec
add esp, 4
mov eax, SYSCALL_WRITE ; write message
mov ebx, STDOUT
mov ecx, msg1
mov edx, len1
int 080h
push 3
call prt_dec
add esp, 4
mov eax, SYSCALL_WRITE ; write message
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 080h
push 5
call prt_dec
add esp, 4
call prt_lf
push 7
call prt_dec
add esp, 4
mov eax, SYSCALL_WRITE ; write message
mov ebx, STDOUT
mov ecx, msg2
mov edx, len2
int 080h
push 4
call prt_dec
add esp, 4
mov eax, SYSCALL_WRITE ; write message
mov ebx, STDOUT
mov ecx, msg3
mov edx, len3
int 080h
push 3
call prt_dec
add esp, 4
call prt_lf
; final exit
;
exit: mov EAX, SYSCALL_EXIT ; exit function
mov EBX, 0 ; exit code, 0=normal
int 080h ; ask kernel to take over
; A subroutine to print a LF, all registers are preserved
prt_lf:
push eax
push ebx
push ecx
push edx
mov eax, SYSCALL_WRITE ; write message
mov ebx, STDOUT
mov ecx, lf
mov edx, 1 ; LF is a single character
int 080h
pop edx
pop ecx
pop ebx
pop eax
ret
Fixes I had on mind (asterisk denotes lines I did touch), hopefully it will be clear from comments what I did:
...
div_loop:
* xor edx, edx ; clear out edx
div ebx ; divide the number by 10
* add dl, '0' ; convert from decimal to char
* mov [esi], dl ; store char in output buffer
inc esi ; move to next spot in output buffer
inc ecx ; keep track of how many chars are added
* test eax,eax ; is there anything left to divide into?
* jnz div_loop ; if so, continue the loop
* ; (jnz is same instruction as jne, but in this context I like "zero" more)
* mov [rlen], ecx ; store number of characters into variable
output_loop:
* ; esi already points beyond last digit, as product of div_loop (removed add)
* dec esi ; point to last/previous digit
mov al, [esi] ; move the char from the div_loop buffer into al
mov [edi], al ; move it into the first position of the converted output buffer
inc edi ; move to the next position of the converted output buffer
dec ecx ; decrement to move backwards through the output buffer
* jnz output_loop ; if it doesn't equal 0, continue loop
print:
mov eax, SYSCALL_WRITE ; write out string
mov ebx, STDOUT
mov ecx, dec_str
* mov edx, [rlen] ; read the number of digits from variable
int 080h
...

Assembly won't print digits

I'm trying to learn assembly. I wanted to write a simple program that counted to 20 and printed out the numbers. I know you have to subtract ascii '0' from a ascii representation of a number to turn it into it's digit, but my implementation just refuses to work. I still get 123456789:;<=>?#ABCD
Here is my code.
section .bss
num resb 1
section .text
global _start
_start:
mov eax, '1'
mov ebx, 1 ; Filehandler 1 = stdout
mov ecx, 20 ; The number we're counting to
mov edx, 1 ; Size of a number in bytes
l1:
mov [num], eax ; Put eax into the value of num
mov eax, 4 ; Put 4 into eax (write)
push ecx ; Save ecx on the stack
mov ecx, num ; print num
int 0x80 ; Do the print
pop ecx ; Bring ecx back from the stack
mov eax, [num] ; Put the value of num into eax
sub eax, '0' ; Convert to digit
inc eax ; Increment eax
add eax, '0' ; Convert back to ascii
loop l1
mov eax,1 ; System call number (sys_exit)
int 0x80 ; Call kernel
Can anyone see what the problem is? I'm totally hitting a brick wall. I'm using nasm to compile and ld to link.

Tower of Hanoi in assembly x86 using arrays

Hi every one I am trying to do a tower of Hanoi in assembly x86 but I am trying to use arrays. So this code gets a number from user as a parameter in Linux, then error checks a bunch of stuff. So now I just want to make the algorithm which use the three arrays i made (start, end, temp) and output them step by step. If someone can help it would be greatly appreciated. `
%include "asm_io.inc"
segment .data ; where all the predefined variables are stored
aofr: db "Argument out of Range", 0 ; define aofr as a String "Argument out of Range"
ia: db "Incorrect Argument", 0 ; define ia as a String "Incorrect Argument"
tma: db "Too many Arguments", 0 ; define tma as a String "Too many Arguments"
hantowNumber dd 0 ; define hantowNumber this is what the size of the tower will be stored in
start: dd 0,0,0,0,0,0,0,0,9 ; this array is where all the rings start at
end: dd 0,0,0,0,0,0,0,0,9 ; this array is where all the rings end up at
temp: dd 0,0,0,0,0,0,0,0,9 ; this array is used to help move the rings
test: dd 0,0,0,0,0,0,0,0,9
; The next couple lines define the strings to show the pegs and what they look like
towerName: db " Tower 1 Tower 2 Tower 3 ", 10, 0
lastLineRow: db "XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXX ", 10, 0
buffer: db " ", 0
fmt:db "%d",10,0
segment .bss ; where all the input variables are stored
segment .text
global asm_main ; run the main function
extern printf
asm_main:
enter 0,0 ; setup routine
pusha
mov edx, dword 0 ; set edx to zero this is where the hantowNumber is saved for now
mov ecx, dword[ebp+8] ; ecx has how many arguments are given
mov eax, dword[ebp+12] ; save the first argument in eax
add eax, 4 ; move the pointer to the main argument
mov ebx, dword[eax] ; save the number into ebx
push ebx ; reserve ebx
push ecx ; reserve ecx
cmp ecx, dword 2 ; compare if there are more the one argument given
jg TmA ; if more then one argument is given then jump Too many Argument (TmA)
mov ecx, 0 ; ecx = 0
movzx eax, byte[ebx+ecx] ; eax is the first character number from the inputed number
sub eax, 48 ; subtract 48 to get the actual number/letter/symbol
cmp eax, 10 ; check if eax is less then 10
jg IA ; if eax is greater then 10 then it is a letter or symbol
string_To_int: ; change String to int procedure
add edx, eax ; put the number in edx
inc ecx ; increase counter (ecx)
movzx eax, byte[ebx+ecx] ; move the next number in eax
cmp eax, 0 ; if eax = 0 then there are no more numbers
mov [hantowNumber], edx ; change hantowNumber to what ever is in edx
je rangeCheck ; go to rangeCheck to check if between 2-8
sub eax, 48 ; subtract 48 to get the actual number/letter/symbol
cmp eax, 10 ; check if eax is less then 10
jg IA ; if eax is greater then 10 then it is a letter or symbol
imul edx, 10 ; multiply edx by 10 so the next number can be added to the end
jmp string_To_int ; jump back to string_To_int if not done
rangeCheck: ; check the range of the number
cmp edx, dword 2 ; compare edx with 2
jl AofR ; if hantowNumber (edx) < 2 then go to Argument out of Range (AofR)
cmp edx, dword 8 ; compare edx with 8
jg AofR ; if hantowNumber (edx) > 8 then go to Argument out of Range (AofR)
mov ecx, [hantowNumber] ; move the number enterd by user in ecx
mov esi, 28 ; esi == 28 for stack pointer counter
setStart: ; set the first array the starting peg
mov [start+esi], ecx ; put ecx into the array
sub esi, 4 ; take one away from stack pointer conter
dec ecx ; take one away from ecx so the next number can go in to the array
cmp ecx, 0 ; compare ecx with 0
jne setStart ; if ecx != 0 then go to setStart loop
; This is the section where the algoritham should go for tower of hanoi
mov ecx, [hantowNumber]
towerAlgorithm:
cmp ecx, 0
jg Exit ; jump to Exit at the end of the program
dec ecx
IA:
mov eax, ia ; put the string in eax
push eax ; reserve eax
call print_string ; output the string that is in eax
call print_nl ; print a new line after the output
pop eax ; put eax back to normal
add esp, 4 ; takes 4 from stack
jmp Exit ; jump to Exit at the end of the program
AofR:
mov eax, aofr ; put the string in eax
push eax ; reserve eax
call print_string ; output the string that is in eax
call print_nl ; print a new line after the output
pop eax ; put eax back to normal
add esp, 4 ; takes 4 from stack
jmp Exit ; jump to Exit at the end of the program
TmA:
mov eax, tma ; put the string in eax
push eax ; reserve eax
call print_string ; output the string that is in eax
call print_nl ; print a new line after the output
pop eax ; put eax back to normal
add esp, 4 ; takes 4 from stack
jmp Exit ; jump to Exit at the end of the program
Exit: ; ends the program when it jumps to here
add esp, 9 ; takes 8 from stack
popa
mov eax, 0 ; return back to C
leave
ret
haha I'm doing the exact same assignment and stuck on the algorithm however though when running your code it seems to identify "too many arguments" even though only one argument is provided, consider this algorithm when dealing with arguments(don't forget ./ is considered the "first argument" since it is the zeroth argument provided):
enter 0,0
pusha
; address of 1st argument is on stack at address ebp+12
; address of 2nd arg = address of 1st arg + 4
mov eax, dword [ebp+12] ;eax = address of 1st arg
add eax, 4 ;eax = address of 2nd arg
mov ebx, dword [eax] ;ebx = 2nd arg, it is pointer to string
mov eax, 0 ;clear the register
mov al, [ebx] ;it moves only 1 byte
sub eax, '0' ;now eax contains the numeric value of the firstcharacter of string

Printing an Int (or Int to String)

I am looking for a way to print an integer in assembler (the compiler I am using is NASM on Linux), however, after doing some research, I have not been able to find a truly viable solution. I was able to find a description for a basic algorithm to serve this purpose, and based on that I developed this code:
global _start
section .bss
digit: resb 16
count: resb 16
i: resb 16
section .data
section .text
_start:
mov dword[i], 108eh ; i = 4238
mov dword[count], 1
L01:
mov eax, dword[i]
cdq
mov ecx, 0Ah
div ecx
mov dword[digit], edx
add dword[digit], 30h ; add 48 to digit to make it an ASCII char
call write_digit
inc dword[count]
mov eax, dword[i]
cdq
mov ecx, 0Ah
div ecx
mov dword[i], eax
cmp dword[i], 0Ah
jg L01
add dword[i], 48 ; add 48 to i to make it an ASCII char
mov eax, 4 ; system call #4 = sys_write
mov ebx, 1 ; file descriptor 1 = stdout
mov ecx, i ; store *address* of i into ecx
mov edx, 16 ; byte size of 16
int 80h
jmp exit
exit:
mov eax, 01h ; exit()
xor ebx, ebx ; errno
int 80h
write_digit:
mov eax, 4 ; system call #4 = sys_write
mov ebx, 1 ; file descriptor 1 = stdout
mov ecx, digit ; store *address* of digit into ecx
mov edx, 16 ; byte size of 16
int 80h
ret
C# version of what I want to achieve (for clarity):
static string int2string(int i)
{
Stack<char> stack = new Stack<char>();
string s = "";
do
{
stack.Push((char)((i % 10) + 48));
i = i / 10;
} while (i > 10);
stack.Push((char)(i + 48));
foreach (char c in stack)
{
s += c;
}
return s;
}
The issue is that it outputs the characters in reverse, so for 4238, the output is 8324. At first, I thought that I could use the x86 stack to solve this problem, push the digits in, and pop them out and print them at the end, however when I tried implementing that feature, it flopped and I could no longer get an output.
As a result, I am a little bit perplexed about how I can implement a stack in to this algorithm in order to accomplish my goal, aka printing an integer. I would also be interested in a simpler/better solution if one is available (as it's one of my first assembler programs).
One approach is to use recursion. In this case you divide the number by 10 (getting a quotient and a remainder) and then call yourself with the quotient as the number to display; and then display the digit corresponding to the remainder.
An example of this would be:
;Input
; eax = number to display
section .data
const10: dd 10
section .text
printNumber:
push eax
push edx
xor edx,edx ;edx:eax = number
div dword [const10] ;eax = quotient, edx = remainder
test eax,eax ;Is quotient zero?
je .l1 ; yes, don't display it
call printNumber ;Display the quotient
.l1:
lea eax,[edx+'0']
call printCharacter ;Display the remainder
pop edx
pop eax
ret
Another approach is to avoid recursion by changing the divisor. An example of this would be:
;Input
; eax = number to display
section .data
divisorTable:
dd 1000000000
dd 100000000
dd 10000000
dd 1000000
dd 100000
dd 10000
dd 1000
dd 100
dd 10
dd 1
dd 0
section .text
printNumber:
push eax
push ebx
push edx
mov ebx,divisorTable
.nextDigit:
xor edx,edx ;edx:eax = number
div dword [ebx] ;eax = quotient, edx = remainder
add eax,'0'
call printCharacter ;Display the quotient
mov eax,edx ;eax = remainder
add ebx,4 ;ebx = address of next divisor
cmp dword [ebx],0 ;Have all divisors been done?
jne .nextDigit
pop edx
pop ebx
pop eax
ret
This example doesn't suppress leading zeros, but that would be easy to add.
I think that maybe implementing a stack is not the best way to do this (and I really think you could figure out how to do that, saying as how pop is just a mov and a decrement of sp, so you can really set up a stack anywhere you like by just allocating memory for it and setting one of your registers as your new 'stack pointer').
I think this code could be made clearer and more modular if you actually allocated memory for a c-style null delimited string, then create a function to convert the int to string, by the same algorithm you use, then pass the result to another function capable of printing those strings. It will avoid some of the spaghetti code syndrome you are suffering from, and fix your problem to boot. If you want me to demonstrate, just ask, but if you wrote the thing above, I think you can figure out how with the more split up process.
; Input
; EAX = pointer to the int to convert
; EDI = address of the result
; Output:
; None
int_to_string:
xor ebx, ebx ; clear the ebx, I will use as counter for stack pushes
.push_chars:
xor edx, edx ; clear edx
mov ecx, 10 ; ecx is divisor, devide by 10
div ecx ; devide edx by ecx, result in eax remainder in edx
add edx, 0x30 ; add 0x30 to edx convert int => ascii
push edx ; push result to stack
inc ebx ; increment my stack push counter
test eax, eax ; is eax 0?
jnz .push_chars ; if eax not 0 repeat
.pop_chars:
pop eax ; pop result from stack into eax
stosb ; store contents of eax in at the address of num which is in EDI
dec ebx ; decrement my stack push counter
cmp ebx, 0 ; check if stack push counter is 0
jg .pop_chars ; not 0 repeat
mov eax, 0x0a
stosb ; add line feed
ret ; return to main
; eax = number to stringify/output
; edi = location of buffer
intToString:
push edx
push ecx
push edi
push ebp
mov ebp, esp
mov ecx, 10
.pushDigits:
xor edx, edx ; zero-extend eax
div ecx ; divide by 10; now edx = next digit
add edx, 30h ; decimal value + 30h => ascii digit
push edx ; push the whole dword, cause that's how x86 rolls
test eax, eax ; leading zeros suck
jnz .pushDigits
.popDigits:
pop eax
stosb ; don't write the whole dword, just the low byte
cmp esp, ebp ; if esp==ebp, we've popped all the digits
jne .popDigits
xor eax, eax ; add trailing nul
stosb
mov eax, edi
pop ebp
pop edi
pop ecx
pop edx
sub eax, edi ; return number of bytes written
ret

Resources