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!
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.
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?
this is my code :
section .bss ;Uninitialized data
average resb 5
num1 resb 5
num2 resb 5
num3 resb 5
section .text
global _start ; make the main function externally visible
_start:
;User prompt
mov eax, 4
mov ebx, 1
mov ecx, messaging
mov edx, lenmessaging
int 0x80
;Read and store the user input
mov eax, 3
mov ebx, 0
mov ecx, num1
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, messaging
mov edx, lenmessaging
int 0x80
;Read and store the user input
mov eax, 3
mov ebx, 0
mov ecx, num2
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 0x80
mov eax, 4
mov ebx, 1
mov ecx, userMsg
mov edx, lenUserMsg
int 0x80
;Read and store the user input
mov eax, 3
mov ebx, 0
mov ecx, num3
mov edx, 5 ;5 bytes (numeric, 1 for sign) of that information
int 0x80
;Output the message
mov eax, 4
mov ebx, 1
mov ecx, dispMsg
mov edx, lenDispMsg
int 0x80
; moving the first number to eax register and second number to ebx
; and subtracting ascii '0' to convert it into a decimal number
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
; add eax and ebx
add eax, ebx
mov ebx, [num3]
sub ebx, '0'
add eax, ebx
mov bl, '3'
sub bl, '0'
div bl
add eax, '0'
mov [average], eax
;Output the number entered
mov eax, 4
mov ebx, 1
mov ecx, average
mov edx, 5
int 0x80
;////////////////
mov eax, 0x1 ; system call number for exit
sub esp, 4 ; OS X (and BSD) system calls needs "extra space" on stack
int 0x80 ; make the system call
section .data ;Data segment
userMsg db 'Please enter a number: ' ;Ask the user to enter a nu
lenUserMsg equ $-userMsg ;The length of the message
dispMsg db 'The average is : '
lenDispMsg equ $-dispMsg
messaging db 'Enter another number : '
lenmessaging equ $-messaging
when I run it ,I have this error :
how can I fix it?
this program is for calculating the average of three numbers.
thanks ;)
I'm fairly new to this PL and I really don't know what I'm doing. It seems my code just takes the first two-digit number and not the second or third.
All I really do is print a prompt asking for a two-digit number, as you can see below. Then it takes the tens and ones digit. Can someone point out what's wrong?
;Prompt to enter first number
...
;Gets the first number
mov eax, 3
mov ebx, 0
mov ecx, num1a
mov edx, 1
int 80h
mov eax, 3
mov ebx, 0
mov ecx, num1b
mov edx, 1
int 80h
;Prompt to enter Second Number
...
;Gets the second number
mov eax, 3
mov ebx, 0
mov ecx, num2a
mov edx, 1
int 80h
mov eax, 3
mov ebx, 0
mov ecx, num2b
;mov edx, 1
int 80h
;Prompt to enter Third Number
...
;Gets the third number
mov eax, 3
mov ebx, 0
mov ecx, num3a
mov edx, 1
int 80h
mov eax, 3
mov ebx, 0
mov ecx, num3b
mov edx, 1
int 80h
It wont let me put anymore code, but the ... in the codes are all the same.
mov eax, 4
mov ebx, 1
mov ecx. prompt
mov edx, promptLen
int 80h
where:
section .data
prompt db 'Enter a two-digit number: '
promptLen equ $-prompt
What you can do is, increase the size of edx when you are reading the value from the user.
mov eax, 3
mov ebx, 0
mov ecx, num1b
mov edx, 32
int 80h