section .data
msg db 'enter number ',10,0
output db '%hd',0
section .bss
val resw 1
section .text
global main
extern printf
extern scanf
main :
push msg
call printf
add esp,4
push val
push output
call scanf
add esp,8
;movzx eax,word[val]
;push eax
push word[val]
push output
call printf
add esp,8
ret
push word[val]
This only pushes a word and you need to have a dword on the stack.
You can do it like:
xor ax,ax
push ax ;Gives a high word of zero, much like your MOVZX did.
push word[val]
Your segmentation fault comes from the fact that you pushed a total of 6 bytes but removed a total of 8 bytes through add esp,8.
Related
I want to compare two strings in x86 assembly. One of them is read from a file and the other one is read from keyboard and both are saved in a variable.
I have no idea how to compare these two variables. I'll be so excited if someone would give me an example or something that can help me.
.386
.model flat, stdcall
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
includelib msvcrt.lib
include Macro.asm
extern exit: proc
extern printf:proc
extern scanf:proc
extern strlen:proc
extern fscanf:proc
extern fopen:proc
extern fprintf:proc
extern fclose:proc
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
public start
.data
format_sir db "%s", 0
format_afisare db "%s", 0
format_zecimal db "&d", 0
mod_citire db "r",0
mod_scriere db "w",0
pointer_fisier_sursa dd 0
pointer_fisier_destinatie dd 0
nume_fisier db 20 dup(0)
fpass db 20 dup(0)
fuser db 20 dup(0)
user db 20 dup(0)
pass db 20 dup(0)
.code
start:
;read file name
citire_fisier:
push offset nume_fisier
push offset format_sir
call scanf
add esp,8
;open the file in read mode
deschide_fisier_citire nume_fisier, mod_citire, pointer_fisier_sursa
cmp pointer_fisier_sursa,0
jne citire_user_parola
jmp citire_fisier
citire_user_parola:
;read from file
Push offset fuser
Push offset format_sir
Push pointer_fisier_sursa
Call fscanf
Add esp,12
push offset fpass
push offset format_sir
push pointer_fisier_sursa
call fscanf
add esp,12
;read from keyboard
push offset user
push offset format_sir
call scanf
add esp,8
push offset pass
push offset format_sir
call scanf
add esp,8
Macro.asm :
deschide_fisier_citire macro nume_fisier, mod_deschidere, pointer_fisier_sursa
push offset mod_deschidere
push offset nume_fisier
call fopen
mov pointer_fisier_sursa ,eax
add esp,8
endm
inchidere_fisier macro pointer_fisier_sursa
push pointer_fisier_sursa
call fclose
add esp,4
endm
In HLA (High Level Assembly ) :more on http://www.plantation-productions.com/Webster/www.artofasm.com/Linux/HTML/StringInstructions.html
cld();
mov( AdrsString1, esi );
mov( AdrsString2, edi );
mov( 7, ecx ); # 7 is the length of the comparison ie size of strings
repe.cmpsb();
In a more classical way :
mov ecx,7
cld
mov esi, offset [stringA]
mov edi, offset [stringB]
repe cmpsb
cmp ecx,0
je strings_are_equal
started practicing with nasm this morning , so i graduated from helloworld to addition and subtraction and then area of a triangle
Now i want to get input (Like Prompts) from the user and then add or subtract or multiply
Following this code
how do i go about it
section .data
msg:
db 'Addition is = %d',10,0
section .text
extern _printf
global _main
_main:
push ebp
mov esp,epb
mov eax,5
add eax,2
push eax
push msg
call _printf
pop ebp
mov esp,ebp
ret
I've written simple assembly code, which uses printf and scanf to write and read numbers, to and from command line respectively.For this particular code, I'm getting output different from given input. It seems that first value printed is [var1]+[var2]*2^8 . However, by increasing size of variables var1 & var2 to 4 bytes, code gives correct output. How?
;assemble and compile with :
;nasm -f elf testing.asm && gcc -m32 -o testing testing.o
extern printf,scanf
;store eax,ebc,ecx,edx onto the stack
%macro push_reg 0
push edx
push ecx
push ebx
push eax
%endmacro
;restore eax,ebx,ecx,edx
%macro pop_reg 0
pop eax
pop ebx
pop ecx
pop edx
%endmacro
section .text
global main
main:
;reads number var1
push_reg
push var1
push formatin
call scanf ;scanf("%d",var1);
add esp,8 ;restoring stack pointer
pop_reg
;reads number var1
push_reg
push var2
push formatin
call scanf ;scanf("%d",var2);
add esp,8 ;restoring stack pointer
pop_reg
;printing number var1
push_reg
push dword[var1]
push formatout
call printf ;printf("%d",content of var1);
add esp,8 ;restoring stack pointer
pop_reg
;printing number var2
push_reg
push dword[var2]
push formatout
call printf ;printf("%d",content of var2);
add esp,8 ;restoring stack pointer
pop_reg
exit:
mov eax,1
int 0x80
section .bss
var1 resb 1
var2 resb 1
section .data
formatout: db "%d",10,0
formatin: db "%d",0
Input:
1
1
Output:
257
1
You told scanf & printf you were scanning/printing integers, which are typically 32-bit (or 4-byte) values. So they behaved as if they were, using that much data at the addresses you provided.
This code gets a name and one number from the user and adds a number (5150) to it. I can't figure out why I'm getting a segmentation fault. I get the fault after the prompt to enter the number. Here's the code:
SECTION .data
askName: db "Enter your name: ",0
askNum: db "Enter an unsigned number no more than four digits: ",0
fResultP1: db "Thank you ",0
fResultP2: db ".",0
fResultP3: db "After adding 5150 to your number, the answer is now: ", 0
formats: db "%s", 0
formatd: db "%d", 0
formatdlf: db "%d",10, 0 ; with line feed
SECTION .bss
name: resb 20
number: resb 4
;answer: resb 5
SECTION .text
extern printf
extern scanf
global main
main:
;;;;;;; set up stack frame
push EBP ; base pointer
mov EBP, ESP ; put stack pntr in EBP
pushad ; pushes all registers on stack
;;;;;;; ask user name
push askName ; push question
call printf ; print question
add ESP, 4 ; clean the stack (pop stack)
;;;;;;; get name input
push name
push formats ; %s (string)
call scanf
add ESP, 8 ; clean the stack (pop stack)
;;;;;;; ask user number
push askNum ; push question
call printf
add ESP, 4 ; pop stack
;;;;;;; get number input
push number
push formatd ; %d (decimal)
call scanf
add ESP, 8 ; pop stack 2X4= 8
;;;;;;; print closing sent
push fResultP1 ; "Thank you "
call printf
add ESP, 4 ; pop stack
push dword [name]
call printf
add ESP, 4 ; pop
push fResultP2 ; "."
call printf
add ESP, 4
push fResultP3 ; "After adding..."
call printf
add ESP, 4 ; pop
mov EAX, dword [number]
add EAX, 5150
push EAX ; push on the added number
push formatdlf ; has line feed
call printf
add ESP, 8 ; pop
;;;;;;; destroy stack frame ;;;;;;;;;;;;;;;;;
popad
mov ESP, EBP
pop EBP
ret
Change push dword [name] to push dword name (or push name). Square bracket is not need. name is the address of the name string.
Me again, with the same kind of problems. So, this time I have created a small function that will display some text on the console. You push 2 arguments on the stack, call the function, see the text and return. This is the code:
start:
push dword MyText ; Pointer to the variable from the .data section
push dword 26 ; Number of characters to write
call ShowText
ret
ShowText:
push ebp
mov ebp, esp
push 0
push WrittenChars ; Pointer to the variable from the .bss section
push dword [ebp + 8] ; Number of characters to write
push dword [ebp + 12] ; MyText
push dword [StdHandle] ; Value of StdHandle, from the .bss section
call WriteConsoleA
pop ebp
ret
[section .data]
MyText db 'Abcdefghijklmnopqrstuvxzw', 0Ah
So, the correct values are pushed and retrieved by WriteConsoleA, the text is displayed correctly but I still get an Access Violation Error, so it looks like ESP is wrong after showing the message. I thought WriteConsoleA would clear the stack of its arguments, I don't know what happens.
ShowText has no pascal calling convetion, so in this case you must adjust the stack yourself.
call ShowText
add esp, 08