IA-32 beginner asm sys_write confusion - linux

I'm using NASM, IA-32 (I think). The homework is to take ASCII from a .txt file and print it to the console in hexadecimal using linux shell input redirection. I think I've got the ascii to hex part figured out, but I'm having a hard time making it print the console correctly. I'm sure I'm just missing something small and silly. The file I'm reading just to test is something simple like this:
ABC
123
The output should be:
41 42 43 0A 31 20 32 20 33 20
The problem is happening in
_hexOut:
I've tried changing more stuff around than I can fit in this post, and I can't figure out where I'm going wrong.
The only output I'm getting is:
41 42 43
section .text
global _start
_start:
mov edx, inBuffSize ; sys_read
mov ecx, inBuffer ; -
mov ebx, 0x00 ; -
mov eax, 0x03 ; -
int 0x80 ; end sys_read
mov [inputLen], eax
cmp eax, 0
jle _exit
_inLeft:
mov ecx, [inCount] ; move
cmp ecx, [inputLen]
je _hexOut
movzx eax, byte [inBuffer + ecx]
mov [temp], al
shr al, 4
mov bl, 9
cmp al, bl
jle _leftIsNumber
mov bl, 10
cmp al, bl
jge _leftIsLetter
_leftIsNumber:
mov ecx, [outCount]
add al, 48
mov [outBuffer + ecx], al
mov ecx, [outCount]
inc ecx
mov [outCount], ecx
jmp _inRight
_leftIsLetter:
mov ecx, [outCount]
add al, 55
mov [outBuffer + ecx], al
mov ecx, [outCount]
inc ecx
mov [outCount], ecx
jmp _inRight
_inRight:
mov ecx, [inCount]
inc ecx
mov [inCount], ecx
movzx eax, byte [temp]
and al, 0x0F
mov bl, 9
cmp al, bl
jle _rightIsNumber
mov bl, 10
cmp al, bl
jge _rightIsLetter
_rightIsNumber:
mov ecx, [outCount]
add al, 48
mov [outBuffer + ecx], al
mov ecx, [outCount]
inc ecx
mov [outBuffer + ecx], byte 32
inc ecx
mov [outCount], ecx
jmp _inLeft
_rightIsLetter:
mov ecx, [outCount]
add al, 55
mov [outBuffer + ecx], al
mov ecx, [outCount]
inc ecx
mov [outBuffer + ecx], byte 32
inc ecx
mov [outCount], ecx
jmp _inLeft
_hexOut:;------------------ PROBLEMS HERE ----------------------
; mov ecx, [inputLen]
; mov [outCount + ecx], byte 0x0A
; inc ecx
; mov [inputLen], ecx
mov edx, [inputLen]
mov ecx, outBuffer
mov ebx, 0x01
mov eax, 0x04
int 0x80
;------------------------------------------------------
_exit:
mov ebx, 0
mov eax, 1
int 0x80
section .data
section .bss
inBuffer resb inBuffSize
outBuffer resb outBuffSize
inBuffSize equ 200
outBuffSize equ 600
inCount resd 1
outCount resd 1
temp resb 1
inputLen resd 1
The second part of the problem is that I need to be able to change how many hex bytes are shown per line in the console, but I can't start to tackle that until I get the first problem solved. Any nudge in the right direction would be appreciated!

Related

NASM unexpected output when printing

I am new have very small problem with assembly NASM in linux. I made simple program for practice that when you put in the text, it adds simple decoration in form of stars. The expected output is:
*********EXAMPLE*********
instead:
*********EXAMPLE
*********
here is the complete code of the program (long) i have use edb to check the code and check EDX register if it match the len take by the null byte check to print correct number of characters.
section .data
prompt db "Please enter a word (MAX: 10 Characters) : ", 0xa, 0xd
plen equ $ - prompt
stars times 9 db "*"
section .bss
text resb 10
section .text
global _start
_start:
mov eax, 4
mov ebx, 1
mov ecx, prompt
mov edx, plen
int 0x80
mov eax, 3
mov ebx, 0
mov ecx, text
mov edx, 11
int 0x80
xor ecx, ecx
mov esi, text
mov ecx, 0
loop1:
inc ecx
cmp byte [esi + ecx], 0x00
jne loop1
push ecx
jmp printexit
printexit:
mov eax, 4
mov ebx, 1
mov ecx, stars
mov edx, 9
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, text
pop edx
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, stars
mov edx, 9
int 0x80
mov eax, 1
int 0x80

Basic assembly calculator assignment not working

We need to do addition, subtraction, multiplication and division with single digits that are entered in using syscalls. For some reason my addition is the only thing that works. I cannot figure out why the rest don't work. All of them outputs nothing, except for multiplication that works if you multiply by 1.
My subtract code:
segment .data
one db 0
two db 0
diff db 0
segment .text
global _start
_start:
mov rax, 0
mov rdi, 0
lea rsi, [one]
mov rdx, 2
syscall
mov rbx, [one]
sub rbx, 48
mov rax, 0
mov rdi, 0
lea rsi, [two]
mov rdx, 2
syscall
sub rbx, [two]
mov [diff], rbx
;xor rbx, rbx
mov rax, 1
mov rdi, 1
mov rdx, 1
lea rsi, [diff]
syscall
mov rax, 60
xor rdi, rdi
syscall
My multiplication code:
segment .data
one db 0
two db 0
multi db 0
segment .text
global _start
_start:
mov eax, 0
mov edi, 0
lea esi, [one]
mov edx, 2
syscall
;mov ebx, [one]
;sub ebx, '0'
mov eax, 0
mov edi, 0
lea rsi, [two]
mov edx, 2
syscall
mov eax, [one]
sub eax, '0'
;mov ecx, [two]
;sub ecx, '0'
mul dword [two]
mov [multi], eax
xor edx, edx
mov eax, 1
mov edi, 1
mov edx, 1
lea esi, [multi]
syscall
mov eax, 60
xor edi, edi
syscall
And division code:
segment .data
one db 0
two db 0
qout db 0
segment .text
global _start
_start:
mov rax, 0
mov rdi, 0
lea rsi, [one]
mov rdx, 2
syscall
;mov rbx, [one]
;sub rbx, '0'
mov rax, 0
mov rdi, 0
lea rsi, [two]
mov edx, 2
syscall
mov eax, [one]
sub eax, '0'
mov edx, 0
mov ecx, two
;sub ecx, '0'
div ecx
mov [qout], [rax]
;xor rdx, rdx
mov rax, 1
mov rdi, 1
mov rdx, 1
lea rsi, [qout]
syscall
mov rax, 60
xor rdi, rdi
syscall
Can someone please tell me why this is not working.
This is my addition for reference:
segment .data
one db 0
two db 0
sum db 0
segment .text
global _start
_start:
mov eax, 0 ;read
mov edi, 0 ;file descriptor
lea esi, [one] ;write to one
mov edx, 2 ;size of input in bytes
syscall
mov ebx, [one]
sub ebx, '0' ;'convert' to int
mov eax, 0 ;again another input
mov edi, 0
lea rsi, [two]
mov edx, 2
syscall
add ebx, [two] ;add two to one
mov [sum], ebx ;move sum into [sum]
xor ebx, ebx ;clear the register
mov eax, 1 ;syscall write
mov edi, 1 ;file descriptor
mov edx, 1 ;output one byte
lea esi, [sum] ;output sum
syscall
mov eax, 60 ;syscall 60 is exit
xor edi, edi ;exit(0)
syscall
I found a solution. In my code I subtracted '0' from both numbers and after the operation I just added '0' again.For Division I did what the solution to this question suggested.

Assembly language and printing result. Fibbonacci sequence

I use Assembly on x86 Linux, with instructions for Intel 8086. I have a problem with my program, which should count the element of Fibbonacci sequence.
This program I run with args, for e.g.:
./fibb 1 2 3 ,
what means: 1st element of sequence is 1, the 2st element is 2 and we want to get the 3rd.
And that example works great, but when I try to run like:
./fibb 1 2 4 ,
then I've got some junk.
Please help me. I'm new in Assembly so please explain me clearly what I'm doing wrong.
Here is my code:
.intel_syntax noprefix
.global _start
.data
var1:
.ascii "To few args\n"
.equ len1, $-var1
var2:
.ascii "Wrong data\n"
.equ len2, $-var2
var3:
.ascii "wrong element of the sequence\n"
.equ len3, $-var3
var4:
.ascii "element of the sequence is higher than 255\n"
.equ len4, $-var4
var5:
.ascii "result: "
.equ len5, $-var5
var6:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
var7:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
var8:
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.text
_start:
jmp ety5
ety1:
mov bh, 48
ety2:
cmp [eax], bh
jz ety3
inc bh
cmp bh, 58
jnz ety2
ety3:
cmp bh, 58
jnz ety4
inc bl
ety4:
inc eax
cmp [eax], byte ptr 0
jnz ety1
ret
ety5:
jmp ety10
invert:
xor ecx, ecx
ety6:
inc ebx
inc ecx
cmp [ebx], byte ptr 0
jnz ety6
ety7:
dec ecx
cmp ecx, 0
jz ety8
mov [ebx], byte ptr 0
dec ebx
cmp [ebx], byte ptr 48
jz ety7
inc ebx
ety8:
inc ecx
push ecx
xor ecx, ecx
ety9:
add ecx, 2
push ecx
dec ebx
mov cl, [eax]
mov ch, [ebx]
mov [eax], ch
mov [ebx], cl
inc eax
pop ecx
cmp ecx, [ebp-8]
jb ety9
pop ecx
ret
ety10:
jmp ety18
ety11:
mov cl, [eax]
cmp cl, 0
jz ety12
sub cl, 48
ety12:
mov ch, [ebx]
sub ch, 48
add cl, dh
xor dh, dh
add cl, ch
cmp cl, 10
jb ety13
inc dh
sub cl, 10
ety13:
add cl, 48
mov [eax], cl
inc eax
inc ebx
cmp [ebx], byte ptr 0
jnz ety11
ety14:
cmp [eax], byte ptr 0
jz ety16
mov cl, [eax]
sub cl, 48
add cl, dh
xor dh, dh
cmp cl, 10
jb ety15
sub cl, 10
inc dh
ety15:
add cl, 48
mov [eax], cl
inc eax
jmp ety14
ety16:
cmp dh, 0
jz ety17
add dh, 48
mov [eax], dh
ety17:
ret
ety18:
jmp ety22
ety19:
mov esi, 3
mov dl, [ecx]
sub dl, 48
loop_mul:
add dl, dl
dec esi
cmp esi,0
jnz loop_mul
add dl, dh
xor dh, dh
cmp dl, 10
jb ety20
sub dl,10
inc dh
ety20:
add dl, 48
mov [ebx], dl
inc ebx
inc ecx
cmp [ecx], byte ptr 0
jnz ety19
cmp dh, 0
jz ety21
add dh, 48
mov [ebx], dh
ety21:
mov ebx, offset var8
ret
ety22:
mov ebp, esp
mov eax, [ebp+8]
cmp eax, 0
jnz ety23
mov eax, 4
mov ebx, 1
mov ecx, offset var1
mov edx, offset len1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety23:
mov eax, [ebp+12]
cmp eax, 0
jnz ety24
mov eax, 4
mov ebx, 1
mov ecx, offset var1
mov edx, offset len1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety24:
mov eax, [ebp+16]
cmp eax, 0
jnz ety25
mov eax, 4
mov ebx, 1
mov ecx, offset var1
mov edx, offset len1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety25:
xor bl, bl
mov eax, [ebp+8]
call ety1
mov eax, [ebp+12]
call ety1
cmp bl, 0
jz ety26
mov eax, 4
mov ebx, 1
mov ecx, offset var2
mov edx, offset len2
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety26:
mov eax, [ebp+16]
call ety1
cmp bl, 0
jz ety27
mov eax, 4
mov ebx, 1
mov ecx, offset var3
mov edx, offset len3
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety27:
xor ebx, ebx;
mov eax, [ebp+16]
mov ecx, [ebp+16]
ety28:
cmp [eax], byte ptr 0
jnz ety29
mov eax, 4
mov ebx, 1
mov ecx, offset var3
mov edx, offset len3
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety29:
cmp [eax], byte ptr 48
jnz ety30
inc eax
inc ecx
jmp ety28
ety30:
inc ecx
cmp [ecx], byte ptr 0
jz ety35
inc ecx
cmp [ecx], byte ptr 0
jz ety33
inc ecx
cmp [ecx], byte ptr 0
jz ety31
mov eax, 4
mov ebx, 1
mov ecx, offset var4
mov edx, offset len4
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety31:
mov cl, [eax]
inc eax
sub cl, 48
ety32:
add ebx, 100
dec cl
cmp cl, 0
jnz ety32
ety33:
mov cl, [eax]
inc eax
sub cl, 48
cmp cl, 0
jz ety35
ety34:
add ebx, 10
dec cl
cmp cl, 0
jnz ety34
ety35:
mov cl, [eax]
sub cl, 48
cmp cl, 0
jz ety37
ety36:
inc ebx
dec cl
cmp cl, 0
jnz ety36
ety37:
cmp ebx, 256
jb ety38
mov eax, 4
mov ebx, 1
mov ecx, offset var4
mov edx, offset len4
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety38:
xor dl, dl
ety39:
dec ebx
inc dl
cmp ebx,0
jnz ety39
mov eax, [ebp+12]
mov ebx, offset var7
xor dh, dh
ety40:
inc eax
inc dh
cmp [eax], byte ptr 0
jnz ety40
xor ch, ch
ety41:
dec eax
dec dh
mov cl, [eax]
mov [ebx], cl
inc ebx
cmp dh, 0
jnz ety41
mov eax, [ebp+8]
mov ebx, offset var6
ety42:
inc eax
inc dh
cmp [eax], byte ptr 0
jnz ety42
ety43:
dec eax
dec dh
mov cl, [eax]
mov [ebx], cl
inc ebx
cmp dh, 0
jnz ety43
cmp dl, 1
jnz ety44
jmp ety46
ety44:
dec dl
cmp dl, 1
jnz ety45
jmp ety47
ety45:
dec dl
cmp dl, 0
jz ety47
push edx
xor dh, dh
mov eax, offset var6
mov ebx, offset var8
mov ecx, offset var7
call ety19
xor dh, dh
call ety11
pop edx
dec dl
cmp dl, 0
jz ety46
push edx
xor dh, dh
mov eax, offset var7
mov ebx, offset var8
mov ecx, offset var6
call ety19
xor dh, dh
call ety11
pop edx
jmp ety45
ety46:
mov eax, 4
mov ebx, 1
mov ecx, offset var5
mov edx, offset len5
int 0x80
mov eax, offset var6
mov ebx, offset var6
call invert
mov eax, 4
mov ebx, 1
mov edx, ecx
mov ecx, offset var6
int 0x80
mov eax, 4
mov ebx, 1
mov [ecx], byte ptr 10
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
ety47:
mov eax, 4
mov ebx, 1
mov ecx, offset var5
mov edx, offset len5
int 0x80
mov eax, offset var7
mov ebx, offset var7
call invert
mov eax, 4
mov ebx, 1
mov edx, ecx
mov ecx, offset var7
int 0x80
mov eax, 4
mov ebx, 1
mov [ecx], byte ptr 10
mov edx, 1
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
int 0x80
This code supposedly fills EAX with the first parameter (a number, not an address).
mov eax, [ebp+8]
call ety1
But at ety1 this code compares the byte at the address EAX with BH.
ety1:
mov bh, 48
ety2:
cmp [eax], bh
jz ety3
How is that going to work?
EDIT
By the time I arrived at the real entry point of this program through a ridiculously long cascade of jumps I totally forgot that this is in fact an application and not just some subroutine. Parameters are thus addresses rendering my answer void!
EDIT2
Are you sure the DS register is properly initialized?

How to compare characters in x86 assembly

I have the two words stored in variables just called first and second. How do I compare the characters of each string to see which one is larger?
section .data
greet: db "Type a word: "
greetL: equ $-greet
section .bss
first: resb 20
second: resb 20
section .text
global _start
_start:
nop
mov eax, 4
mov ebx, 1
mov ecx, greet
mov edx, greetL
int 80H
mov eax, 3
mov ebx, 0
mov ecx, first
mov edx, 20
int 80H
then I just do the same thing to get the second word
I dunno, cmp I suppose...
xor ecx, ecx ; index
top
mov al, [first + ecx]
cmp [second + ecx], al
jb first_is_bigger
ja second_is_bigger
cmp al, LF ; LF equ 10
je they_are_equal
inc ecx
jmp top
That's untested. I've been having a lot of brain flatulence lately - better check me. If the pesky user enters more than 20 characters, you may be in deep muddy water...

64bit NASM file handling problems

I managed to write a NASM program on my 64bit Linux system which removes non-letter symbols from an input and prints each word in separate line. The problem is that I get RCX = -1 where i have to get the readed character number , and as a result I get segmentation fault. I've already spent hours trying to figure out how to fix this bug. Hope you guys will be able to help me. Thanks in advance.
Heres my code:
section .data
file1 db "data", 0
file2 db "results", 0
text times 255 db 0
textSize equ $ - text
buff times 255 db 0
buffSize equ $ - buff
section .text
global main
main:
mov rax, 2
mov rdi, file1
mov rsi, 0 ;read only
mov rdx, 0x7777
syscall ;open file1
mov rbx, rax ;save fd to rbx
mov rsi, text ; a pointer to the current character
mov rax, 0
mov rdi, rbx ;fd of file1
mov rsi, text
mov rdx, textSize
syscall ;read the text from file1
mov rax, 3
mov rdi, rbx
syscall ;close file1
mov rcx, rax ; rcx - character counter
mov rbx, buff ;rbx will be our buffer
cmp rcx, 0
je exit ; if nothing to read - exit
process_loop1:
mov dl, byte[rsi]
cmp byte[rsi], 0x41 ; "A"
jl inc1
cmp byte[rsi], 0x5a ; "Z"
jle save
cmp byte[rsi], 0x61 ; "a"
jl inc1
cmp byte[rsi], 0x7a ; "z"
jle save
jmp inc1 ;check text
inc1:
inc rsi
dec rcx
jnz process_loop1
jmp print
save:
mov byte [ebx], dl
jmp inc2 ;save letters
inc2:
inc rsi
inc rbx
dec rcx
jnz process_loop2
jmp print
process_loop2:
mov dl, byte[rsi]
cmp byte[rsi], 0x41 ; "A"
jl enter
cmp byte[rsi], 0x5a ; "Z"
jle save
cmp byte[rsi], 0x61 ; "a"
jl enter
cmp byte[rsi], 0x7a ; "z"
jle save
jmp enter
enter:
mov byte [ebx], 10 ;enter
inc rsi
inc rbx
dec rcx
jnz process_loop1
jmp print
print:
mov rax, 2
mov rdi, file2
mov rsi, 1 ;write only
mov rdx, 0x7777
syscall ;open file2
mov rbx, rax ;save fd to rbx
mov rax, 1
mov rdi, rbx
mov rsi, buff
mov rdx, buffSize
syscall ;print result
mov rax, 3
mov rdi, rbx
syscall ;close file2
jmp exit
exit:
mov rax, 60
mov rdi, 0
syscall
You have a sys_close between the sys_read and the time you try to check the number of bytes received. Thus, you are checking the return value of the close, not the read. Also note that rcx is destroyed by syscall so you can't just move up the mov rcx, rax line.
Also, in a few places you use [ebx] instead of [rbx].
Furthermore, you probably want use O_CREAT for the result file and only write as many bytes as you have processed, not buffSize.
section .data
filename db 'AVG.asm'
section .bss
buffer resb 2000
fd_in resb 1
section .text
global _start
_start:
mov rax,2
mov rdi,filename
mov rsi,0
mov rdx,0777
syscall
mov [fd_in],rax
mov rax,0
mov rdi,[fd_in]
mov rsi,buffer
mov rdx,2000
syscall
mov rax,1
mov rdi,1
mov rsi,buffer
mov rdx,2000
syscall
mov rax,3
mov rdi,[fd_in]
syscall
mov rax,60
mov rdi,0
syscall

Resources