I'm new to writing assembly code and I'm having trouble printing out the values of my array using a loop. The code I have prints out the value of the counter and the not the values in the array, can someone please explain what I'm doing wrong, also how do I point to the top of the array? I have tried using different registers, but nothing seems to be working. My professor asks that I do it this way (if it seems inefficient):
.386
.model flat
ExitProcess PROTO NEAR32 stdcall, dwExitCode:dword
Include io.h
cr equ 0DH
Lf equ 0AH
.stack 4096
.data
newline byte CR, LF, 0
whitespace byte 32,32,0
arr dword 10 dup(?)
n dword 2
string byte 40 dup(?)
prompt byte "Please enter a value: ", 0
origArr byte "Original Array", 0
.code
_start:
mov ecx,n ; number of values in the array
lea ebx,arr ; address of the array
sub edi, edi
top: cmp ecx, 0
je done
output prompt
input string, 40
atod string
mov [arr+edi], ecx
add edi, 4
loop top
done: output origArr
mov ecx, n
call myproc
INVOKE ExitProcess, 0
PUBLIC _start
myproc proc near32
.data
val_str byte 11 dup(?), 0
.code
push eax
push edi
push ecx
sub edi,edi ; index register
top2: mov eax, [ebx+edi]
dtoa val_str, eax
output val_str
add edi,4 ; modify esi rather than ebx
loop top2
pop ecx
pop edi
pop eax
ret
myproc endp
END
Any suggestions are appreciated.
mov [arr+edi], ecx
You're storing the loop counter, rather than the return value of atod.
Related
; Input x and y, output min of the two numbers
.586
.MODEL FLAT
INCLUDE io.h
.STACK 4096
.DATA
number DWORD ?
array DWORD 20, 15, 62, 40, 18
nbrElts DWORD 5
prompt BYTE "Enter value:", 0
string BYTE 80 DUP (?)
resultLbl BYTE "Position", 0
result BYTE 11 DUP (?), 0
.CODE
_MainProc PROC
input prompt, string, 20 ; read ASCII characters
atod string ; convert to integer
mov number, eax ; store in memory
push nbrElts ; 3rd parameter (# of elements in array)
lea eax, array ; 2nd parameter (address of array)
push eax
push number ; 1st parameter (value from user)
call searchArray ; searchArray(number, array, 5)
add esp, 12
dtoa result, eax ; convert to ASCII characters
output resultLbl, result ; output label and result
mov eax, 0 ; exit with return code 0
ret
_MainProc ENDP
; searchArray(int x, array, int y)
;
searchArray PROC
push ebp ; save base pointer
mov ebp, esp ; establish stack frame
push eax ; save registers
push ebx
push esi
push ecx
push edx
mov ebx, [ebp+8] ; x, value from user
mov esi, [ebp+12] ; address of array
mov ecx, [ebp+16] ; y, number of elements
mov edx, 1
mov ecx, 5
forLoop:
mov eax, [esi] ; a[i]
cmp eax, ebx ; eax = ebx ?
je isEqual
;cmp eax, ebx
add esi, 4
inc edx
loop forLoop
;mov eax, 0
cmp edx, 6
je notEqual
isEqual:
mov eax, edx
jmp exitCode
notEqual:
mov eax, 0
jmp exitCode
exitCode:
mov eax, edx
pop edx ; restore EBP
pop ecx ; restore EAX
pop esi
pop ebx
pop ebp
ret ; return
searchArray ENDP
END ; end of source code
The pops at the end of the function need to match the pushes at the beginning of the function. If they don't match, the stack pointer ends up in the wrong place and the ret returns to the wrong place.
In your case, you have an extra push without a corresponding pop.
The reason to push registers at the beginning and pop them at the end is to preserve their values. But you don't want to preserve the value of eax. You want to return a different value, the result of the function. So there is absolutely no reason to push eax.
I'm trying to convert some strings representing binary numbers into their actual values, using a conversion function defined in a different file.
Here's my code:
main.asm
bits 32
global start
%include 'convert.asm'
extern exit, scanf, printf
import exit msvcrt.dll
import scanf msvcrt.dll
import printf msvcrt.dll
section data use32 class=data
s DB '10100111b', '01100011b', '110b', '101011b'
len EQU $ - s
res times len DB 0
segment code use32 class=code
start:
mov ESI, s ; move source string
mov EDI, res ; move destination string
mov ECX, len ; length of the string
mov EBX, 0
repeat:
lodsb ; load current byte into AL
inc BL
cmp AL, 'b' ; check if its equal to the character b
jne end ; if its not, we need to keep parsing
push dword ESI ; push the position of the current character in the source string to the stack
push dword EDI ; push the position of the current character in the destination string to the stack
push dword EBX ; push the current length to the stack
call func1 ; call the function
end:
loop repeat
push dword 0
call [exit]
convert.asm
func1:
mov ECX, [ESP] ; first parameter is the current parsed length
mov EDI, [ESP + 4] ; then EDI
mov ESI, [ESP + 8] ; and ESI
sub ESI, ECX
parse:
mov EDX, [ESI]
sub EDX, '0'
mov [EDI], EDX
shl dword [EDI], 1
inc ESI
loop parse
ret 4 * 3
I noticed that I keep getting access violation errors after the function call though. ESI has some random value after the call. Am I doing something wrong? I think the parameter pushing part should be alright. Inside the conversion function, the parameters should be accessed in the reverse order. But that's not happening for some reason.
I'm also pretty sure that I did the compiling/linking part alright using nasm and alink.
nasm -fobj main.asm
nasm -fobj convert.asm
alink main.obj convert.obj -oPE -subsys console -entry start
This
is how my output should look like.
Here is my code:
.586
.MODEL FLAT
;Exit Process PROTO NEAR32 stdcall,dwExitCode:DWORD
INCLUDE io.h
cr EQU 0dh
Lf EQU 0ah
.STACK 4096
.DATA
prompt1 BYTE "Enter the decimal number: ", 0
asciiIn DW 4 DUP (?)
msgLabel BYTE "Result",00h; message Label
msgText BYTE "Your output" ;
BYTE "Decimal: "
asciiDecimal DW 4 DUP (?),10
BYTE "Binary: "
asciiBinary DW 4 DUP(?), 10
BYTE "Hex: "
asciiHex DW 4 DUP (?), 10
decimal WORD 0
STR1 DW 4 DUP (?)
STR2 DW 4 DUP (?)
HEX WORD 0
.CODE
_MainProc PROC
xor eax, eax ; clear eax
xor ebx, ebx ; clear ebx
xor ecx, ecx ; clear ecx
lp : input prompt1, asciiIn, 10 ; prompt user to enter number
atow asciiIn ; convert from ascii to word and store in eax
LEA ESI,STR1
; MOV EAX,NO
MOV BH,00
MOV BL,2
L1:DIV BL
ADD AH,'0'
MOV BYTE PTR[ESI],AH
MOV AH,00
INC ESI
INC BH
CMP AL,00
JNE L1
MOV CL,BH
LEA ESI,STR1
LEA EDI,STR2
MOV CH,00
ADD ESI,ECX
DEC ESI
L2:MOV AH,BYTE PTR[ESI]
MOV BYTE PTR[EDI],AH
DEC ESI
INC EDI
LOOP L2
done :
; output messages
output msgLabel,msgText
wtoa asciiDecimal, asciiIn
output asciiBinary,STR2
wtoa asciiHex, HEX
mov eax, 0
ret
_MainProc ENDP
END
Comment #
Using Programming Exercise 6 in Chapter 4 as a starting point,
write a program that generates the first 47 values in the Fibonacci
series, stores them in an array of doublewords, and writes the
doubleword array to a disk file.
#
INCLUDE c:\Irvine\Irvine32.inc
FIB_COUNT = 47 ; number of values to generate
.data
fileHandle DWORD ?
filename BYTE "fibonacci.bin",0
array DWORD FIB_COUNT DUP(?)
.code
main2sub PROC
; Generate the array of values
mov esi, OFFSET array
mov ecx, LENGTHOF array
call generate_fibonacci
; Create the file, call CreateOutputFile
mov edx,OFFSET filename
call CreateOutputFile
mov fileHandle, eax
; Write the array to the file, call WriteToFile
mov eax, fileHandle
mov edx, OFFSET array
mov ecx, FIB_COUNT * 4
call WriteToFile
; Close the file, call CloseFile
mov eax, fileHandle
call CloseFile
exit
main2sub ENDP
;------------------------------------------------------------
generate_fibonacci PROC USES eax ebx ecx edx
;
; Generates fibonacci values and stores in an array.
; Receives: ESI points to the array,
; ECX = count
; Returns: nothing
;------------------------------------------------------------
mov ebx, 1
mov ecx, 0
L1:
add ebx, ecx
mov [esi], eax
call WriteDec
call Crlf
inc esi
xchg ebx, eax
loop L1 ;end of looping
ret
generate_fibonacci ENDP
END main2sub
It is my first semester learning about Assembly Language. Im not sure what to do with this error message "fatal error LNK1120: 1 unresolved externals". Can anyone help me out?
The linker couldn't find the library-files Irvine32.lib, Kernel32.Lib and/or User32.Lib. They are in the same folder as Irvine32.inc
The easiest way is to inform ML about those libraries with a MASM-directive. Insert following three lines right behind the INCLUDE c:\Irvine\Irvine32.inc:
INCLUDELIB c:\Irvine\Irvine32.lib
INCLUDELIB c:\Irvine\Kernel32.lib
INCLUDELIB c:\Irvine\User32.lib
This is my first assembler program in masm32. Using vis studio 2012. And this is just one procedure in a program to convert input into an ascii chart with decimal, hex and ascii output. I've been trying to figure this out for 8 hours, and I know it's going to be something really simple.
It gets through all the computation, but during the pop and return phase it crashes into an unhandled exception when accessing the EIP(i think). Also, all my registers are set to 0 except ebx and I don't know why, but it may have something to do with it.
This is just the procedure to convert from the input string to a decimal value.*
My inputStr is:
inputStr db 16 DUP(0)
.code
main proc
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
lea esi, outputStr1
call PrintString
lea esi, inputStr
call GetString
call StrtoNum
invoke ExitProcess, 0 ;****This is the next line when it crashes***
main endp
StrtoNum proc ;going to hex first
pushad
pushfd
mov bl, 1 ;mov 1 into bl for later multiplying
whilemorechar:
mov al,byte ptr [esi]
cmp al, 0 ;stuff
je ConvertDone ;if null then we are done here
;esi is pointing to the string to be converted
;cmp bl,0
;jnz decrement
cmp al, 0h
je ConvertDec
sub al, 30h ;get first string byte to dec number 0-9
push ax ;push last digit to stack
inc esi ;gets to next string byte
inc cl ;make note of decimal position in string
jmp whilemorechar ;jump for next place in string
ConvertDec: ;reverse is done, now turn into decimal number
cmp cl, 0 ;compare counter to 0
jz ConvertDone ;if counter is 0, start comparing numbers
pop ax ;pop last on stack
mul bl ;multiply place value by input byte
add dx, ax ;add decimal value into dl
mov al, 10d ;move 10 into al
mul bx ;multiply 10 and bl value to get next
mov bx, ax ;mov decimal place into bl for next loop
dec cl ;decrement counter
jmp ConvertDec ;loop through again for next decimal place
ConvertDone:
mov ebx, 0
popfd ;pop flags
popad ;pop registers
ret ;return to caller
StrtoNum endp