0

Going from high to low lever language I got to assembly. Now at the very beginning, I wrote a simple age program (I'm not clear how to get system time yet so I just used another input). I get Segmentation Fault (core dumped) after I enter the final input. Here is my code:

section .text
global _start       

_start:                     

mov edx, lenask
mov ecx, ask
mov ebx, 1
mov eax, 4
int 0x80

mov edx, 5
mov ecx, input
mov ebx, 2
mov eax, 3
int 0x80

mov edx, lenask2
mov ecx, ask2
mov ebx, 1
mov eax, 4
int 0x80

mov edx, 5
mov ecx, input2
mov ebx, 2
mov eax, 3
int 0x80

mov eax, input2
mov ebx, input
sub eax, ebx

push eax

mov edx, lenanswer
mov ecx, answer
mov ebx, 1
mov eax, 4
int 0x80

pop eax

mov edx, 7
mov ecx, eax
mov ebx, 1
mov eax, 4
int 0x80

section .data

ask db "What is your age?"
lenask equ $-ask
ask2 db "What is today's year?"
lenask2 equ $-ask2
answer db "The age you were born was: "
lenanswer equ $-answer

section .bss 

input resb 5
input2 resb 5

An example of what happens:

What is your age?45
What is today's year?2015
The age you were born was: Segmentation fault

It should have done:

What is your age?45
What is today's year?2015
The age you were born was: 1970
Michael Petch
  • 46,082
  • 8
  • 107
  • 198
  • Why are you using `stderr` (2) for input instead of `stdin` (0)? – Michael Nov 20 '15 at 11:23
  • The 7 should've been a 5, that's my bad, but it doesn't solve it. And for the stdin, I haven't thought of that, but changing it to 0 still doesn't help – user3348294 Nov 20 '15 at 12:03
  • 1
    The issue is that the `int $0x80` system call for writing to a file requires a pointer to a string buffer to print be placed in _ECX_ . When you print out the result you attempt to do this `mov ecx, eax`. You moved the calculated value into _ECX_, but that is not a pointer. You need to convert the value in _EAX_ to the string representation of that value, and pass the address of that string in _ECX_ . An example of an integer to string conversion function (_int_to_string_) can be found in this [SO answer](http://stackoverflow.com/a/19312503/3857942). – Michael Petch Nov 20 '15 at 17:48
  • 1
    You also need to do something similar when inputting. Read input returns a string pointer in _EAX_. You need to convert the strings you get into integers and then do subtraction. Your subtraction simply subtracts the two pointers. The _string_to_int_ function in the same [SO answer](http://stackoverflow.com/a/19312503/3857942) is an example of such a conversion. – Michael Petch Nov 20 '15 at 18:02
  • 1
    @MichaelPetch That sounds a lot like an answer. Comments are not supposed to be used for answers; please avoid that, thanks. – edmz Nov 20 '15 at 18:36
  • 1
    @black . I disagree in this case. This question is basically an indirect duplicate of the other Stackoverflow question, except the OP doesn't know the root cause of the issue. I don't answer the _HOW_ to convert. IMHO, the real answer they want is in http://stackoverflow.com/a/19312503/3857942 . That answer is NASM/Linux/32-bit, but the question is not technically a duplicate of this, but the answer would solve this problem. – Michael Petch Nov 20 '15 at 18:39
  • I'm voting to close this question as off-topic because the question comes down to converting string to integers (and integers to string) in NASM/Linux/32-Bit. This [StackOverflow Answer](http://stackoverflow.com/a/19312503/3857942) would solve this question. The two questions aren't duplicates but the answer is. – Michael Petch Nov 20 '15 at 18:45
  • @OzgurBar If you want to add an answer to this question, be my guest. – Michael Petch Nov 20 '15 at 18:47
  • 1
    @MichaelPetch I don't think it's a _direct_ dup, as you say. Therefore, answer by telling the user what's wrong (that is, the actual problem -- missing int-to-string conversion in this case) and point them to a question where that's been already covered. That's the behavior I think works best in these cases. – edmz Nov 20 '15 at 18:48
  • I have informed the user that the answers they seek are in other SO Answers, via a comment, and since I'm not on SO for reputation, I don't need to place an answer that already exists elsewhere on this site. I recommend upvoting the other answer. – Michael Petch Nov 20 '15 at 18:51
  • @MichaelPetch That must be the problem. I've ran the debugger just to check it again and it located the segmentation problem at 0x004014 of _start. While the actual start label is at instruction 0x004000. Does that mean anything special? And thank you for pointing me to the solution. – user3348294 Nov 20 '15 at 20:44
  • And I've corrected the input aswell, still the debugger says the error is at the mentioned location. – user3348294 Nov 20 '15 at 21:08

1 Answers1

1

The problem is that int 0x80 with eax set to 4 calls the kernel's sys_write function (i.e. a write system call) which expects a pointer to a string. By providing a integer to the function call the kernel will think that the integer is a pointer to a memory location. Because 1970 is not a valid pointer it will raise a -EFAULT. To bypass this you need to code a ToString function to convert the number to a string and then pass the pointer to the converted string.

The Segmentation Fault itself is caused by not having a sys_exit call. The reason for this is that the program will continue past the end of your code (usally into a bunch of 00 00)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Markian
  • 322
  • 1
  • 12
  • EAX=4 / `int 0x80` is the [`write` system call](https://man7.org/linux/man-pages/man2/write.2.html). Passing it a bad pointer will make it return `-EFAULT` because it's a system call; bad pointers to system calls don't directly raise SIGSEGV. The fault here is from falling off the end of `.text`, often into some `00 00` bytes (`add [eax], al`, and EAX = `-EFAULT` isn't a valid pointer either. But this time we're dereferencing in user-space). Single-step it with a debugger to see. [What happens if there is no exit system call in an assembly program?](https://stackoverflow.com/q/49674026) – Peter Cordes Jan 10 '23 at 16:25
  • Didn’t notice the lack of a sys_exit call. Fixed. – Markian Jan 10 '23 at 16:39