Assembler sysTime giving error on executing - linux

i'm learning Assembler (Nasm, Linux, Ubuntu 16.4, x86_64)
and getting Trouble using the sys_time call (mov eax, 13).
section .bss
time: resb 30;
section .data
msg: db "The Time is:";
msgLen: equ $-msg;
blank: db 0x0a;
blankLen: equ $-blank;
section .text
global _start:
_start:
mov eax, 13;
mov ebx, time;
int 80h;
mov eax, 4;
mov ebx, 1;
mov ecx, msg;
mov edx, msgLen;
int 80h;
mov eax, 4;
mov ebx, 1;
mov edx, time;
mov ecx, 30;
int 80;
mov eax, 4;
mov ebx, 1;
mov ecx, blank;
mov edx, blankLen;
int 80h;
mov eax, 1;
mov ebx, 0;
int 80h;
The error message is
(translated with google) (Written dump ) segfaulting if someone knows german here the German error Message Speicherzugriffsfehler (Speicherabzug geschrieben)
my thougts: maybe resb reserves space for a string, but how can i convert the Integer to a string?? Or do i have to declare a Integer?
or is my kernel broke?

You have int 80 instead of int 80h on one line. And ecx/edx have the values other way.
After printing msg the next code should be:
mov eax, 4
mov ebx, 1
mov ecx, time
mov edx, 30
int 80h
(It will not do, what you expect, anyway, as the sys_time does not return string, so you can't display it directly).
Checking the sys_time docs on internet... you should call it rather with xor ebx,ebx (NULL buffer pointer), and use the returned eax value. Giving it the buffer pointer is now obsolete way of call. It's number of seconds since Epoch (1970-01-01 00:00:00 +0000 (UTC)).
So at the beginning of your code you can do:
mov eax, 13
xor ebx,ebx
int 80h
mov [time],eax
It's still not solving how to display it (nor I will even try, depends what you really want to achieve, whether just linking against clib is enough for you, and then use the C functions to format the time, or you want to create the seconds_number->time_string formatter from scratch on your own).

Related

Converting user input to all caps in assembly (NASM) [duplicate]

This question already has answers here:
X86 NASM Assembly converting lower to upper and upper to lowercase characters
(5 answers)
X86 Assembly Converting lower-case to uppercase
(1 answer)
Closed 3 years ago.
I want to change the string to all caps, although I am having trouble getting the length of the input. What i have tried so far is moving the address of the message into a registrar then indexing through the string and also increment a counter variable. Then comparing the char in the address to a '.' (signifying the end of the message) and if its found not to be equal it will recall this block of statements. At least this is what I want my code to do. Not sure if this is even the right logic. I know there are alot of errors and its messy but I'm learning so please just focus on my main question. thank you! EDIT: the input i use is 'this is a TEST.'
;nasm 2.11.08
SYS_Write equ 4
SYS_Read equ 3
STDIN equ 0
STDOUT equ 1
section .bss
message resb 15
counter resb 2
section .data
msg1: db 'Enter input (with a period) that I will turn into all capitals!',0xa ;msg for input
len1 equ $- msg1
section .text
global _start
_start:
mov eax, SYS_Write ; The system call for write (sys_write)
mov ebx, STDOUT ; File descriptor 1 - standard output
mov ecx, msg1 ; msg to print
mov edx, len1 ; len of message
int 0x80 ; Call the kernel
mov eax, SYS_Read ;system call to read input
mov ebx, STDIN ;file descriptor
mov ecx, message ;variable for input
mov edx, 15 ;size of message
int 0x80 ;kernel call
mov [counter], byte '0'
getLen:
mov eax, message
add eax, [counter]
inc byte [counter]
cmp eax, '.'
jne getLen
mov eax, SYS_Write ; this is to print the counter to make sure it got the right len
mov ebx, STDOUT
mov ecx, counter
mov edx, 2
int 0x80
jmp end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov eax, [message]
;add eax, counter
cmp eax, 90
jg toUpper
toUpper:
sub eax, 32
mov [message], eax
mov eax, SYS_Write ; The system call for write (sys_write)
mov ebx, STDOUT ; File descriptor 1 - standard output
mov ecx, message ; Put the offset of hello in ecx
mov edx, 10 ; helloLen is a constant, so we don't need to say
int 0x80 ; Call the kernel
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
end:
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return code of 0 (no error)
int 0x80 ;

How to return of Called Functions multiple times/NASM

I am trying to return of a function, which also calls a function, but I get a SIGSEV.
MY ASSEMBLER: Linux, Unix nasm 64 +ld
sample:
;something
call myFunction
myFunction:
call func2
ret
func2:
;do sth
ret
One possibility is to push the Pointer to the stack, but the Stack is Limited, isn't it? And I need a solution for doing this n-times, whereas n should be able to stand for infinity.
Another possibility is to call the function and do a label for returning, but when I hava a function, which is called by different routines, I'm runnning into another problem :(
Is there an elegant way of doin' this?
Ox, so I got the suggestion, I should try it as it could work.
I tried it with this code:
section .data
test : db "test", 0x0a; length: 5
input: db "433", 0x00
blank: db 0xa
section .bss
section .text
global _start:
_start:
mov eax, 4
mov ebx, 1
mov ecx, input
mov edx, 4
int 80h
mov eax, input
call strToInt
mov [input], eax
mov eax, 4
mov ebx, 0
mov ecx, test
mov edx, 5
int 80h
ret
mov eax, 1
mov ebx, 0
int 80h;
strToInt:
mov ebx, 0; counter
mov ecx, 0; ecx is 4 the result
conversion_loop:
cmp BYTE[eax], 0
jz leave_loop
sub byte[eax], 48
inc eax
inc ebx
cmp ebx ,9
jge leave_loop
jmp conversion_loop
leave_loop:
call hey
ret
hey:
mov eax, 4
mov ebx, 0
mov ecx, test
mov edx, 5
int 80h
ret
(sorry for the code, this long -.-)
the result is:
433test
test
SEGFAULT
Does this clarify this a bit?
Look at this lines:
int 80h
ret
I think this ret is jump out of your code segment. You must remove ret to call sys_exit function to complete programm gracefully.

Writing integer to console gives Segmentation Fault

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
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)

nasm, read syscall reads over buffer size

I have the following code. It works ok except one thing which limits its usage in other programs. When I run it in the debugger, Linux read system call returns value always bigger than the specified buffer size. Why is it and how to fix it, because it doesn't let the program to loop through the buffer array without a segmentation fault?
SECTION .data
address dd "log.txt", 0
badf dd "Bad file!",0
buffsize dd 1024
size dd 1024
filedesc dd 0
section .bss
buf resb 1024
SECTION .text
global main
main:
mov ebx, address
mov eax, 5 ; open(
mov ecx, 0 ; read-only mode
int 80h ; );
mov [filedesc], eax
read_loop:
mov ebx, [filedesc] ; file_descriptor,
mov eax, 3 ; read(
mov ecx, buf ; *buf,
mov edx, buffsize ; *bufsize
int 80h ; );
test eax, eax
jz done
js badfile
mov eax, 4 ; write(
mov ebx, 1 ; STDOUT,
mov edx, buffsize
mov ecx, buf ; *buf
int 80h
jmp read_loop
badfile:
mov eax, 4 ; write(
mov ebx, 1 ; STDOUT,
mov edx, 10
mov ecx, badf ; *buf
int 80h
done:
mov eax, 6
mov ebx, [filedesc]
int 0x80
mov ebx,0
mov eax,1
int 0x80
mov edx, buffsize ; *bufsize
Is wrong since buffsize is declared as follows:
buffsize dd 1024
the above code will move the address of buffsize to edx. What you want is:
mov edx, [buffsize]
which will move the value stored at buffsize to edx.
You have a few of those type of errors in there.
Could it be a negative error return code?
I don't see any test in your code for negative values.

NASM Linux Assembly Printing Integers

I am trying to print a single digit integer in nasm assembly on linux. What I currently have compiles fine, but nothing is being written to the screen. Can anyone explain to me what I am doing wrong here?
section .text
global _start
_start:
mov ecx, 1 ; stores 1 in rcx
add edx, ecx ; stores ecx in edx
add edx, 30h ; gets the ascii value in edx
mov ecx, edx ; ascii value is now in ecx
jmp write ; jumps to write
write:
mov eax, ecx ; moves ecx to eax for writing
mov eax, 4 ; sys call for write
mov ebx, 1 ; stdout
int 80h ; call kernel
mov eax,1 ; system exit
mov ebx,0 ; exit 0
int 80h ; call the kernel again
This is adding, not storing:
add edx, ecx ; stores ecx in edx
This copies ecx to eax and then overwrites it with 4:
mov eax, ecx ; moves ecx to eax for writing
mov eax, 4 ; sys call for write
EDIT:
For a 'write' system call:
eax = 4
ebx = file descriptor (1 = screen)
ecx = address of string
edx = length of string
After reviewing the other two answers this is what I finally came up with.
sys_exit equ 1
sys_write equ 4
stdout equ 1
section .bss
outputBuffer resb 4
section .text
global _start
_start:
mov ecx, 1 ; Number 1
add ecx, 0x30 ; Add 30 hex for ascii
mov [outputBuffer], ecx ; Save number in buffer
mov ecx, outputBuffer ; Store address of outputBuffer in ecx
mov eax, sys_write ; sys_write
mov ebx, stdout ; to STDOUT
mov edx, 1 ; length = one byte
int 0x80 ; Call the kernel
mov eax, sys_exit ; system exit
mov ebx, 0 ; exit 0
int 0x80 ; call the kernel again
From man 2 write
ssize_t write(int fd, const void *buf, size_t count);
In addition to the other errors that have been pointed out, write() takes a pointer to the data and a length, not an actual byte itself in a register as you are trying to provide.
So you will have to store your data from a register to memory and use that address (or if it's constant as it currently is, don't load the data into a register but load its address instead).

Resources