x^3/2+1
if x=2 the answer it gives is 4290776301. i tried to do anything i could and i think the problem might be in ascii decoding or smth but i don't know what else i can do here.
%include "in_out.asm"
SECTION .data
msg: DB 'Вариант 6. Мой пример: f(x) = x*x*x/2 + 1.Введи, какой x я бы поставил: ', 0
pink: DB 'Ответ на пример: ', 0
SECTION .bss
x: resb 80
SECTION .text
GLOBAL _start
_start:
mov eax, msg
call sprintLF
mov ecx, x
mov edx, 80
call sread
mov eax, x
call atoi
mov ebx, [x]
mov eax, x
mul ebx
mul ebx
mov ebx, 2
xor ebx, edx
div ebx
add eax, 1
mov [x],eax
mov eax, pink
call sprint
mov eax, [x]
call iprintLF
call quit
looking forward for any help, thank you!
if x=2 the answer it gives is 4290776301
mov eax, x
mul ebx
The result can get so big because you are not starting the multiplication from the inputted number but rather from the address of the buffer x. In NASM mov eax, x loads the address of x, and mov eax, [x] loads the value stored at x.
call atoi
mov ebx, [x]
mov eax, x
atoi already leaves its result in the EAX register. You only need to copy it to the EBX register. call atoi mov ebx, eax.
mov ebx, 2
xor ebx, edx
div ebx
For the division by 2, you needed to clear the EDX register. You've accidently (typo) XORed the divider instead! And of course, dividing by 2 is better done using a shift to the right shr eax, 1.
A solution
mov eax, msg
call sprintLF
mov eax, x
call scanf
mov eax, x
call atoi ; -> EAX
mov ebx, eax ; ((X^3)/2)+1
imul ebx, eax
imul ebx, eax
shr ebx, 1
inc ebx
mov eax, pink
call sprint
mov eax, ebx
call iprintLF
Related
I'm a novice Assembly x86 Learner, and i want to add two numbers (5+5) and print the result on the screen.
here is my code:
global _start
section .text
_start:
mov eax, 5
mov ebx, 5
add eax, ebx
push eax
mov eax, 4 ; call the write syscall
mov ebx, 1 ; STDOUT
pop ecx ; Result
mov edx, 0x1
int 0x80
; Exit
mov eax, 0x1
xor ebx, ebx
int 0x80
Correct me please
Another approach to convert an unsigned integer to a string and write it:
section .text
global _start
_start:
mov eax, 1234567890
mov ebx, 5
add eax, ebx
; Convert EAX to ASCII and store it onto the stack
sub esp, 16 ; reserve space on the stack
mov ecx, 10
mov ebx, 16
.L1:
xor edx, edx ; Don't forget it!
div ecx ; Extract the last decimal digit
or dl, 0x30 ; Convert remainder to ASCII
sub ebx, 1
mov [esp+ebx], dl ; Store remainder on the stack (reverse order)
test eax, eax ; Until there is nothing left to divide
jnz .L1
mov eax, 4 ; SYS_WRITE
lea ecx, [esp+ebx] ; Pointer to the first ASCII digit
mov edx, 16
sub edx, ebx ; Count of digits
mov ebx, 1 ; STDOUT
int 0x80 ; Call 32-bit Linux
add esp, 16 ; Restore the stack
mov eax, 1 ; SYS_EXIT
xor ebx, ebx ; Return value
int 0x80 ; Call 32-bit Linux
I'm trying to print Hi 10 times. This is my code.
section .data
msg db "Hi"
section .text
global _start
_start:
mov cx, 10
L1:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, 3
int 0x80
dec cx
jnz L1
mov eax, 1
mov ebx, 0
int 0x80
gdb reports that mov edx, 3 overwrites the cx register to some crazy value and so the loop keeps going forever.
What am i doing wrong? Is it because they are the same register?
How does one program in assembly with so few registers?
Compiling on centos with nasm and ld
Thanks
You're looking at the wrong line. The problem is "mov ecx, msg". ECX is the extended register of which CX is the lower part, so you're writing over it.
It's best to save your loop counter on the stack, because who knows that the 'int' call might change. Add 'push cx' (or ecx) after 'L1:'. and 'pop cx' after the 'int' call to preserve the contents of the register.
This code fixes it:
section .data
msg db "Hi"
counter dw 10
section .text
global _start
_start:
L1:
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, 2
int 0x80
mov cx, [counter]
dec cx
mov [counter], cx
jnz L1
mov eax, 1
mov ebx, 0
int 0x80
move the value into a variable and then dec it then put it back
I'm working on conversions of c programs to NASM and I've been having issues with segmentation faults after the program runs. It will do what its supposed to do but will provide a segmentation fault message at the end of it.
The code is:
segment .data
out_less db "Z is less than 20.", 10, 0
out_greater db "Z is greater than 20.", 10, 0
out_equal db "Z is equal to 20! Yeah Z!", 10, 0
segment .bss
segment .text
global main
extern printf
ret
main:
mov eax, 10
mov ebx, 12
mov ecx, eax
add ecx, ebx ;set c (ecx reserved)
mov eax, 3
mov ebx, ecx
sub ebx, eax ;set f (ebx reserved)
mov eax, 12
mul ecx
add ecx, 10 ;(a+b*c) (ecx reserved)
mov eax, 6
mul ebx
mov eax, 3
sub eax, ebx
mov ebx, eax ;(d-e*f) (ebx reserved) reassign to ebx to keep eax open for manipulation
mov eax, ecx
div ebx
mov ecx, eax
add ecx, 1 ;(a+b*c)/(d-e*f) + 1
cmp ecx, 20
jl less
jg greater
je equal
mov eax, 0
ret
less:
push out_less
call printf
ret
jmp end
greater:
push out_greater
call printf
ret
jmp end
equal:
push out_equal
call printf
ret
jmp end
end:
mov eax, 0
ret
I'm not sure whats causing the fault because the program does actually run correctly any thoughts?
Thanks!
Update - this seems to work:
segment .data
out_less db "Z is less than 20.", 10, 0
out_greater db "Z is greater than 20.", 10, 0
out_equal db "Z is equal to 20! Yeah Z!", 10, 0
segment .bss
segment .text
global main
extern printf
main:
mov eax, 10
mov ebx, 12
mov ecx, eax
add ecx, ebx ;set c (ecx reserved)
mov eax, 3
mov ebx, ecx
sub ebx, eax ;set f (ebx reserved)
mov eax, 12
mul ecx
add ecx, 10 ;(a+b*c) (ecx reserved)
mov eax, 6
mul ebx
mov eax, 3
sub eax, ebx
mov ebx, eax ;(d-e*f) (ebx reserved) reassign to ebx to keep eax open for manipulation
mov eax, ecx
div ebx
mov ecx, eax
add ecx, 1 ;(a+b*c)/(d-e*f) + 1
cmp ecx, 20
jl less
jg greater
jmp equal
less:
push out_less
call printf
add esp,4
jmp exit
greater:
push out_greater
call printf
add esp,4
jmp exit
equal:
push out_equal
call printf
add esp,4
exit:
mov eax, 0
ret
end
How do I write a variable to a file using NASM?
For example, if I execute some mathematical operation - how do I write the result of the operation to write a file?
My file results have remained empty.
My code:
%include "io.inc"
section .bss
result db 2
section .data
filename db "Downloads/output.txt", 0
section .text
global CMAIN
CMAIN:
mov eax,5
add eax,17
mov [result],eax
PRINT_DEC 2,[result]
jmp write
write:
mov EAX, 8
mov EBX, filename
mov ECX, 0700
int 0x80
mov EBX, EAX
mov EAX, 4
mov ECX, [result]
int 0x80
mov EAX, 6
int 0x80
mov eax, 1
int 0x80
jmp exit
exit:
xor eax, eax
ret
You have to implement ito (integer to ascii) subsequently len for this manner. This code tested and works properly in Ubuntu.
section .bss
answer resb 64
section .data
filename db "./output.txt", 0
section .text
global main
main:
mov eax,5
add eax,44412
push eax ; Push the new calculated number onto the stack
call itoa
mov EAX, 8
mov EBX, filename
mov ECX, 0x0700
int 0x80
push answer
call len
mov EBX, EAX
mov EAX, 4
mov ECX, answer
movzx EDX, di ; move with extended zero edi. length of the string
int 0x80
mov EAX, 6
int 0x80
mov eax, 1
int 0x80
jmp exit
exit:
xor eax, eax
ret
itoa:
; Recursive function. This is going to convert the integer to the character.
push ebp ; Setup a new stack frame
mov ebp, esp
push eax ; Save the registers
push ebx
push ecx
push edx
mov eax, [ebp + 8] ; eax is going to contain the integer
mov ebx, dword 10 ; This is our "stop" value as well as our value to divide with
mov ecx, answer ; Put a pointer to answer into ecx
push ebx ; Push ebx on the field for our "stop" value
itoa_loop:
cmp eax, ebx ; Compare eax, and ebx
jl itoa_unroll ; Jump if eax is less than ebx (which is 10)
xor edx, edx ; Clear edx
div ebx ; Divide by ebx (10)
push edx ; Push the remainder onto the stack
jmp itoa_loop ; Jump back to the top of the loop
itoa_unroll:
add al, 0x30 ; Add 0x30 to the bottom part of eax to make it an ASCII char
mov [ecx], byte al ; Move the ASCII char into the memory references by ecx
inc ecx ; Increment ecx
pop eax ; Pop the next variable from the stack
cmp eax, ebx ; Compare if eax is ebx
jne itoa_unroll ; If they are not equal, we jump back to the unroll loop
; else we are done, and we execute the next few commands
mov [ecx], byte 0xa ; Add a newline character to the end of the character array
inc ecx ; Increment ecx
mov [ecx], byte 0 ; Add a null byte to ecx, so that when we pass it to our
; len function it will properly give us a length
pop edx ; Restore registers
pop ecx
pop ebx
pop eax
mov esp, ebp
pop ebp
ret
len:
; Returns the length of a string. The string has to be null terminated. Otherwise this function
; will fail miserably.
; Upon return. edi will contain the length of the string.
push ebp ; Save the previous stack pointer. We restore it on return
mov ebp, esp ; We setup a new stack frame
push eax ; Save registers we are going to use. edi returns the length of the string
push ecx
mov ecx, [ebp + 8] ; Move the pointer to eax; we want an offset of one, to jump over the return address
mov edi, 0 ; Set the counter to 0. We are going to increment this each loop
len_loop: ; Just a quick label to jump to
movzx eax, byte [ecx + edi] ; Move the character to eax.
movsx eax, al ; Move al to eax. al is part of eax.
inc di ; Increase di.
cmp eax, 0 ; Compare eax to 0.
jnz len_loop ; If it is not zero, we jump back to len_loop and repeat.
dec di ; Remove one from the count
pop ecx ; Restore registers
pop eax
mov esp, ebp ; Set esp back to what ebp used to be.
pop ebp ; Restore the stack frame
ret ; Return to caller
I have a program below that tries to take input from the user and repeat that same string until the user enters it again. (It's a personal learning project)
However, I am having some severe diffuculty in getting it to perform correctly. In a past thread here, you can see the input, pun intended, that other users have provided on this problem.
%include "system.inc"
section .data
greet: db 'Hello!', 0Ah, 'Please enter a word or character:', 0Ah
greetL: equ $-greet ;length of string
inform: db 'I will now repeat this until you type it back to me.', 0Ah
informL: equ $-inform
finish: db 'Good bye!', 0Ah
finishL: equ $-finish
newline: db 0Ah
newlineL: equ $-newline
section .bss
input: resb 40 ;first input buffer
check: resb 40 ;second input buffer
section .text
global _start
_start:
greeting:
mov eax, 4
mov ebx, 1
mov ecx, greet
mov edx, greetL
sys.write
getword:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 40
sys.read
sub eax, 1 ;remove the newline
push eax ;store length for later
instruct:
mov eax, 4
mov ebx, 1
mov ecx, inform
mov edx, informL
sys.write
pop edx ;pop length into edx
mov ecx, edx ;copy into ecx
push ecx ;store ecx again (needed multiple times)
mov eax, 4
mov ebx, 1
mov ecx, input
sys.write
mov eax, 4 ;print newline
mov ebx, 1
mov ecx, newline
mov edx, newlineL
sys.write
mov eax, 3 ;get the user's word
mov ebx, 0
mov ecx, check
mov edx, 40
sys.read
sub eax, 1
push eax
xor eax, eax
checker:
pop ecx ;length of check
pop ebx ;length of input
mov edx, ebx ;copy
cmp ebx, ecx ;see if input was the same as before
jne loop ;if not the same go to input again
mov ebx, check
mov ecx, input
secondcheck:
mov dl, [ebx]
cmp dl, [ecx]
jne loop
inc ebx
inc ecx
dec eax
jnz secondcheck
jmp done
loop:
pop edx
mov ecx, edx
push ecx
mov eax, 4
mov ebx, 1
mov ecx, check
sys.write ;repeat the word
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, newlineL
sys.write
mov eax, 3 ;replace new input with old
mov ebx, 0
mov ecx, check
mov edx, 40
sys.read
jmp checker
done:
mov eax, 1
mov ebx, 0
sys.exit
Example output would yield:
Hello!
Please enter a word or character:
INPUT: Nick
I will now repeat this until you type it back to me.
Nick
INPUT: Nick
N
INPUT: Nick
INPUT: Nick
And that goes on forever until is ^C it to death. Any ideas on the problem?
Thanks.
instruct leaves two items on the stack, which are consumed by checker the first time round the loop. But they are not replaced for the case where you go round the loop again. This is the most fundamental problem in your code (there may be others).
You could find this by running with a debugger and watching the stack pointer esp; but it can be seen just by looking at the code -- if you take everything out except for the stack manipulation and branches, you can clearly see that the checker -> loop -> back to checker path pops three items but only pushes one:
greeting:
...
getword:
...
push eax ;store length for later
instruct:
...
pop edx ;pop length into edx
...
push ecx ;store ecx again (needed multiple times)
...
push eax
checker:
pop ecx ;length of check
pop ebx ;length of input
...
jne loop ;if not the same go to input again
...
secondcheck:
...
jne loop
...
jnz secondcheck
jmp done
loop:
pop edx
...
push ecx
...
jmp checker
done:
...
There are better ways to keep long-lived variables than trying to shuffle them around on the stack like this with push and pop.
Keep them in a data section (the .bss you already have would be suitable) instead of on the stack.
Allocate some space on the stack, and load/store them there directly. e.g. sub esp, 8 to reserve two 32-bit words, then access [esp] and [esp+4]. (The stack should be aligned to a 32-bit boundary, so always reserve a multiple of 4 bytes.) Remember to add esp, 8 when you've finished using it.
(These are essentially the equivalent of what a C compiler would do for global (or static) variables, and local variables, respectively.)