NASM one wrong way checking data - nasm

So, I write a program that creates matrix 4x5 and I have almost done it. I store data in the strings in order to check what information is stored there. When I enter data properly - Ok, but if I make even just one mistake (for example +12asd) then I see my program works again from the "array[3][0]" when I have entered it. What is wrong?
; Task: write a program that allows to enter 2-D array 4x5. Show only 2 first columns.
section .bss ; The section intended for uninitilizated data
string_00 resb 7
string_01 resb 7
string_02 resb 7
string_03 resb 7
string_04 resb 7
string_10 resb 7
string_11 resb 7
string_12 resb 7
string_13 resb 7
string_14 resb 7
string_20 resb 7
string_21 resb 7
string_22 resb 7
string_23 resb 7
string_24 resb 7
string_30 resb 7
string_31 resb 7
string_32 resb 7
string_33 resb 7
string_34 resb 7
section .data ; The section designed for using initilizated data
pointer_0 dd string_00, string_01, string_02, string_03, string_04
pointer_1 dd string_10, string_11, string_12, string_13, string_14
pointer_2 dd string_20, string_21, string_22, string_23, string_24
pointer_3 dd string_30, string_31, string_32, string_33, string_34
pointer dd pointer_0, pointer_1, pointer_2, pointer_3
external_counter dd 0
internal_counter dd 0
section .text
global _start
_start:
call _check
ex:
mov ebx, 0
mov eax, 1
int 0x80
_print:
mov ebx, 1
mov eax, 4
int 0x80
ret
_enter:
mov edx, 7
mov ebx, 0
mov eax, 3
int 0x80
ret
_make_esi:
mov eax, [pointer]
mov ebx, [external_counter]
mov esi, [eax + ebx * 4]
mov ebx, [internal_counter]
add ebx, ebx
add ebx, ebx
add ebx, ebx
add esi, ebx
ret
_check:
call _make_esi
cmp esi, string_01
je ex
mov ecx, esi
call _enter
inc dword [internal_counter]
jmp _check

Related

why does this code throw a seg fault in assembly

When compiled and ran this piece of assembly code throws a Segmentation fault which I can't figure out
section .data
section .bss ; Uninitialized data
x resb 5
section .text
global _start ; entry point for linker (ld)
_start:
; Grab input from user
mov eax, 3 ; system call number (sys_read)
mov ebx, 2
mov ecx, x
mov edx, 5 ; 5 bytes 1 for the sign 4 for the numbers
;Output the number entered
mov eax, 4 ; system call number (sys_write)
mov ebx, 1
mov ecx, x
mov edx, 5
int 0x80 ; kernel call
The goal is to declare a number inside the code and then output the value to the screen
looks like I forgot to do the kernel calls that is why it results in a segfault
section .data
section .bss ; Uninitialized data
x resb 5
section .text
global _start ; entry point for linker (ld)
_start:
; Grab input from user
mov eax, 3 ; system call number (sys_read)
mov ebx, 2
mov ecx, x
mov edx, 5 ; 5 bytes 1 for the sign 4 for the numbers
int 0x80 ; kernel call
;Output the number entered
mov eax, 4 ; system call number (sys_write)
mov ebx, 1
mov ecx, x
mov edx, 5
int 0x80 ; kernel call
; return 0
mov eax, 1
mov ebx, 0
int 80h ; kernel call

NASM Assembly - Multiply Two Numbers Input by the User

I'm super new to assembly, and I've spent literally hours trying to figure this out. The program I'm making is supposed to take two numbers from zero to nine, then multiply them and show the correct answer (ex: 9 times 3 is 27). I need to have the 2 numbers be input from the user with the notation of "space number space number" (an example could be " 5 3"). I tried making the code without input (hardcode the numbers) and that works, but when I try to make the numbers come from input, the result is wrong. The program is supposed to take two numbers from zero to nine, then multiply them. I really can't figure out what's wrong...Any help at all would be very much appreciated.
When I enter: " 5 3" it outputs "? 4" (it should be 15)
When I enter: " 9 3" it still outputs "? 4" (it should be 27)
When I enter: "5 3" it outputs "?6"
When I enter: "9 3" it outputs "??4"
When I check var1 and var2 (by making it print them after them being read), the numbers are correct. As in, if " 5 3" is entered var1 does print 5 and var2 does print 3. Even if the spaces are changed, var1 and var2 print the correct numbers (so if I enter "5 3" var1 is still 5, and var2 is still 3).
My professor just explained what to do to get input, but I'm not 100% sure how it works. I find it odd that the output is different depending on where the spaces are, as var1 and var2 should both be accepting 2 bytes.
My code that's incorrect:
;this program multiplies two numbers input by the user, being able to solve with two digits
;the notation for the input should be space number space number (ex:" 9 3")
section .data
section .bss
var1 resb 2
var2 resb 2
result resb 2
tensdigit resb 2
onesdigit resb 2
section .text
global _start
_start:
;reads & saves user input for var1
mov eax, 3
mov ebx, 0
mov ecx, var1
mov edx, 2 ;2 bytes of info
int 80h
;reads & saves user input for var2
mov eax, 3
mov ebx, 0
mov ecx, var2
mov edx, 2 ;2 bytes of info
int 80h
mov al, [var1]
; sub al, '0' ;not sure if this is needed or not
mov bl, [var2]
; sub bl, '0'
;multiply bl by al
mul bl
; sub ax, '0'
mov [result], ax
;divide by ten
mov ax, 0 ;set the register to 0! Very important to avoid errors
mov ax, [result]
mov bx, 10
div bx ;divide by ten
mov [tensdigit], al ;this should have 1 if using 12 (2 if 24, etc)
mov ax, [result]
sub ax, 10
mov [result], ax ;move new number into result
mov al, [result]
mov bl, 10
div bl
;find the remainder
mov [onesdigit], ah
add [tensdigit], word '0' ;add 0 to ensure it's considered a number
add [result], word '0'
add [onesdigit], word '0'
;print tensdigit
mov eax, 4
mov ebx, 1
mov ecx, tensdigit
mov edx, 2
int 80h
;print onesdigit
mov eax, 4
mov ebx, 1
mov ecx, onesdigit
mov edx, 2
int 80h
;system exit
mov eax,1
mov ebx,0
int 80h;
This is my code when the numbers are hardcoded (this one multiplies the numbers correctly):
;this program adds two numbers, being able to solve with two digits
section .data
section .bss
var1 resb 2
var2 resb 2
result resb 2
tensdigit resb 2
onesdigit resb 2
section .text
global _start
_start:
;setup the variables
mov [var1], word 9
mov [var2], word 3
mov al, [var1]
mov bl, [var2]
mul bl
mov [result], ax
;divide by ten
mov ax, 0 ;set the register to 0! Very important to avoid errors
mov ax, [result]
mov bx, 10
div bx ;divide by ten
mov [tensdigit], al ;this should have 1 if using 12 (2 if 24, etc)
mov ax, [result]
sub ax, 10
mov [result], ax ;move new number into result
mov al, [result]
mov bl, 10
div bl
;find the remainder
mov [onesdigit], ah
add [tensdigit], word '0' ;add 0 to ensure it's considered a number
add [result], word '0'
add [onesdigit], word '0'
;print tensdigit
mov eax, 4
mov ebx, 1
mov ecx, tensdigit
mov edx, 2
int 80h
;print onesdigit
mov eax, 4
mov ebx, 1
mov ecx, onesdigit
mov edx, 2
int 80h
mov eax,1
mov ebx,0
int 80h;

Assembly on Linux: unexpected behaviour from Assembly [duplicate]

This question already has answers here:
In NASM labels next to each other in memory are printing both strings instead of first one
(1 answer)
How does $ work in NASM, exactly?
(2 answers)
Closed 4 years ago.
running the code below generates a file with Welcome to jj Shashwat as content. what i didn't get is why does it writes Shashwat at the end of the file, Shashwat is in a totally different variable. Any idea why does this happen?
section .text
global _start ;must be declared for using gcc
_start:
;create the file
mov eax, 8
mov ebx, file_name
mov ecx, 0777 ;read, write and execute by all
int 0x80 ;call kernel
mov [fd_out], eax
; close the file
mov eax, 6
mov ebx, [fd_out]
;open the file for reading
mov eax, 5
mov ebx, file_name
mov ecx, 2 ;for read/write access
mov edx, 0777 ;read, write and execute by all
int 0x80
mov [fd_out], eax
; write into the file
mov edx,len ;number of bytes
mov ecx, msg ;message to write
mov ebx, [fd_out] ;file descriptor
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
; close the file
mov eax, 6
mov ebx, [fd_out]
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
file_name db 'myfile.txt', 0
msg db 'Welcome to jj', 0
mgafter db ' Shashwat', 0
lntwo equ $-mgafter
len equ $-msg
section .bss
fd_out resb 1
fd_in resb 1
info resb 26
That's because you said len equ $-msg after defining both msg and msgafter, so len is set to the length of both msg and msgafter, making your write call write both strings. This is because len equ $-msg means “set len to be the difference between the current location ($) and the location of msg.”
To fix this, move the len equ $-msg line right after the definition of msg.

How do I use a BSS var to move string into register NASM

I'm trying to move a string into a BSS var, I've tried various methods but I have a feeling that unless I hardcode the string or use a read to grab the string I'm fighting a futile battle, the problem I'm having is although I can get the text data into the right register more data accompanies it which trashes the output and some how trashes the value of vdlen (if I directly assign a value to ecx in WriteFile the proper length is put however attempting to use vdlen causes it to way off radar)
How do I get the right results (ie "Hello!" in "text.txt") ?
section .bss
vdata resw 10
vdlen resb 3
vfd resb 1
vfn resb 15
err resb 2
section .text
mov eax,vfn
mov dword [eax],'test'
mov dword [eax+3], '.txt'
mov ebx,vdata
mov dword [ebx], 'Hell'
mov dword [ebx+3],'o!'
mov ecx,vdlen
mov [ecx], 0x03h
jmp WriteFile
ProgramEnd:
mov eax,1
mov ebx,[err]
int 80h
WriteFile:
mov eax,5 ;Syscall for open()
mov ebx,vfn
mov ecx, 65 ; mode Write-only Create
mov edx, 420 ; permissions rw-r-r
int 80h ; Linux Kernel Interrupt
mov [vfd],eax ; get file descriptor
mov eax,4 ;Syscall for write()
mov ebx,[vfd] ; FD argument
mov ecx,[vdata] ; this is where my issue is
mov edx,[vdlen] ; length of vdata
int 80h
mov [err],eax
jmp ProgramEnd
After the extremely helpful advice provided by rkbh and MikeCat to the OP, the OP got it working:
section .bss
vfd resb 5
vfn resb 15
vdlen resb 5
vdata resw 10
section .text
global _start
_start:
mov eax,vfn
mov dword [eax],'test'
mov dword [eax+4],'.txt'
mov ebx,vdata
mov dword [vdata], 'Hell'
mov dword [vdata+4],0 ;nullbyte ?
mov word [vdlen],4
jmp WriteFile
ProgramEnd:
mov eax,1
mov ebx,[err]
int 80h
WriteFile:
mov eax,5 ; open syscall
mov ebx,vfn
mov ecx, 65 ; Write Only, Create Only File Mode
mov edx, 420 ; ugo: RW-R-R
int 80h
mov [vfd],eax
mov eax,4
mov ebx,[vfd]
mov ecx,vdata
mov edx,[vdlen]
int 80h
mov byte [err],0 ;this essentially does nothing since write()
;returns the number of bytes written so I can't actually get an
;error code unless I want to check for err == 0 or
;err >= expectedWriteSize
jmp ProgramEnd
TL;DR: OP was trying to cram 6 bytes into 4 bytes using DWORD MOV's and had mis-specified the size for vdlen.

Comparing 16 bit numbers in nasm produces wrong results

I have just started learning assembly. I am coding nasm in 32 bit mode. I am trying to compare 3 numbers inputted by the user and print the largest number. However, I cannot seem to correctly compare the numbers if I only reserve 16 bits for each number using resb 2. I do, however, get correct results when I reserved 32 bits for the numbers using resw 2. I cannot understand why this is the case. Here is my code:
SYS_EXIT equ 1
SYS_WRITE equ 4
SYS_READ equ 3
STD_IN equ 0
STD_OUT equ 1
segment .data
msg1 db "Enter first number",0xA
msg1_len equ $- msg1
msg2 db "Enter second number",0xA
msg2_len equ $- msg2
msg3 db "Enter third number",0xA
msg3_len equ $- msg3
msg4 db "Largest number is ",0xA
msg4_len equ $- msg4
segment .bss
num1 resb 2
num2 resb 2
num3 resb 2
res resb 2
section .text
global _start
_start:
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg1
mov edx, msg1_len
int 0x80
mov eax, SYS_READ
mov ebx, STD_IN
mov ecx, num1
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg2
mov edx, msg2_len
int 0x80
mov eax, SYS_READ
mov ebx, STD_IN
mov ecx, num2
mov edx, 2
int 0x80
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg3
mov edx, msg3_len
int 0x80
mov eax, SYS_READ
mov ebx, STD_IN
mov ecx, num3
mov edx, 2
int 0x80
mov ecx, [num1]
cmp ecx, [num2]
jg check_third
mov ecx, [num2]
check_third:
cmp ecx, [num3]
jg result
mov ecx, [num3]
result:
mov [res], ecx
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, msg4
mov edx, msg4_len
int 0x80
mov eax, SYS_WRITE
mov ebx, STD_OUT
mov ecx, res
mov edx, 2
int 0x80
exit:
mov eax, SYS_EXIT
int 0x80
Sorry if it has a lot of repeating code. I understand why I need 2 bytes to store keyboard input when supposedly ascii characters are only 8 bits in length (Since the standard input will also read the new line character aside from the digit). However, I do not know a lot of things about how nasm works such as how it reacts when I move 16 bits of memory to a 32 bit register, how it compares 32 bit and 16 bit values (will it do signed expansion or just pad 0 before binary subtraction). I would truly appreciate it if someone can recommend me resources on the technicalities of nasm aside from explaining why I need to reserve 2 words to do the comparison.
Nasm does not keep record of the size of the data at label like some other assemblers. Suppose you enter 1, 2 and 3. Bytes stored at your labels will then be:
num1: db 0x31, 0x0A
num2: db 0x32, 0x0A
num3: db 0x33, 0x0A
When you move 32 bits of data from label num1, you are actually also moving data from num2. Because little endian machines store least significant bytes first, you get something like:
mov ecx, 0x0A320A31 ; high bytes contain num2 and low bytes contain num1
cmp ecx, 0x0A330A32 ; high bytes contain num3 and low bytes contain num2
jg check_third
mov ecx, 0x0A330A32
check_third:
cmp ecx, 0x00000A33 ; high bytes contain res and low bytes contain num3
jg result
.....
resw 2 (or resd 1) would work because reserved memory is initialized to zeros. As Frank stated in the comment, you should use cl instead of ecx because 8 bits is all you need to handle in this case.

Resources