I'm pretty new to fasm and I just recently started learning about procedures. My problem is that I have a proc and I want it to sort my list in a certain way. But when I run my code it just seems to sort some random numbers from memory. I don't quite know why it happens and I would appreciate any help.
Here's the code:
format PE gui 5.0
include 'D:\Flat Assembler\INCLUDE\win32a.inc'
entry start
section '.data' data readable writable
mas1 dw 2, -3, 1, -1, 3, -2, 5, -5, -4, 4
N = ($ - mas1) / 2
numStr db N dup('%d '), 0
strStr db '%s', 0
undefStr db 'undefined', 0
buff db 50 dup(?)
Caption db 'Result', 0
section '.code' code readable executable
start:
stdcall bubble, mas1
cinvoke wsprintf, buff, numStr
invoke MessageBox, 0, buff, Caption, MB_OK + MB_ICONINFORMATION
invoke ExitProcess, 0
proc bubble, mas:word
mov ecx, 0
mov ebx, 0
outerLoop:
cmp ecx, 10
je done
mov ebx, 2
innerLoop:
mov eax, 0
mov edx, 0
cmp [mas+ebx], 0 ;if(mas[j] > 0)
jge continue ;continue
mov ax, [mas+ebx-2]
cmp ax, [mas+ebx]
jle continue
mov dx, [mas+ebx]
mov [mas+ebx-2], dx
mov [mas+ebx], ax
continue:
cmp ebx, 18 ;10
je innerDone
add ebx, 2 ;inc ebx
jmp innerLoop
innerDone:
inc ecx
jmp outerLoop
done:
mov ecx, 0
mov ebx, 0
mov ebx, 18
mov ecx, N
print:
mov eax, 0
mov ax, [mas+ebx]
cwde
push eax
sub ebx, 2
loop print
ret
endp
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL',\
user32,'USER32.DLL'
include 'D:\Flat Assembler\INCLUDE\API\kernel32.inc'
include 'D:\Flat Assembler\INCLUDE\API\user32.inc'
Error 1
stdcall bubble, mas1
...
proc bubble, mas:word
The parameter mas1 is an address and is pushed to the stack as a dword. Therefore you should not limit the argument mas to a word.
What your bubble procedure needs is the full address of the array. You get this via mov esi, [mas] that FASM will encode as if you would have written mov esi, [ebp+8]. EBP+8 is where the first argument (and in your program the only argument) resides, when the standard prologue push ebp mov ebp, esp is used.
Error 2
In your bubble procedure you push the resulting array to the stack hoping to have wsprintf use it from there, but once the bubble procedure executes its ret instruction, the epilogue code as well as the ret instruction itself will start eating your array and even return to the wrong address in memory!
If you're going to return an array via the stack, then store it above the return address and the argument(s). That's why I wrote in my program below:
sub esp, N*4 ; Space for N dwords on the stack
stdcall bubble, mas1
Error 3
cmp [mas+ebx], 0 ;if(mas[j] > 0)
jge continue ;continue
Your BubbleSort is wrong because you don't allow positive numbers to get compared!
Furthermore you make too many iterations that also continu for too long.
I tested below program on FASM 1.71.22 Don't forget to change the paths!
format PE gui 5.0
include 'C:\FASM\INCLUDE\win32a.inc'
entry start
section '.data' data readable writable
mas1 dw 2, -3, 1, -1, 3, -2, 5, -5, -4, 4
N = ($ - mas1) / 2
numStr db N-1 dup('%d, '), '%d', 0
;strStr db '%s', 0
;undefStr db 'undefined', 0
buff db 50 dup(?)
Caption db 'Result', 0
section '.code' code readable executable
start:
sub esp, N*4 ; Space for N dwords on the stack
stdcall bubble, mas1
cinvoke wsprintf, buff, numStr
invoke MessageBox, 0, buff, Caption, MB_OK + MB_ICONINFORMATION
invoke ExitProcess, 0
proc bubble uses ebx esi, mas
mov esi, [mas] ; Address of the array
mov ecx, (N-1)*2 ; Offset to the last item; Max (N-1) compares
outerLoop:
xor ebx, ebx
innerLoop:
mov ax, [esi+ebx]
mov dx, [esi+ebx+2]
cmp ax, dx
jle continue
mov [esi+ebx+2], ax
mov [esi+ebx], dx
continue:
add ebx, 2
cmp ebx, ecx
jb innerLoop
sub ecx, 2
jnz outerLoop
mov ebx, (N-1)*2
toStack:
movsx eax, word [esi+ebx]
mov [ebp+12+ebx*2], eax
sub ebx, 2
jnb toStack
ret
endp
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL',\
user32,'USER32.DLL'
include 'C:\FASM\INCLUDE\API\kernel32.inc'
include 'C:\FASM\INCLUDE\API\user32.inc'
Error 2 revisited
IMO returning the resulting array through the stack would make better sense if your bubble procedure didn't modify the original array.
But in your present code you do, so...
Once you strike the toStack snippet from the bubble procedure, you can simply (after returning from the bubble procedure) push the word-sized elements of the array to the stack as dwords followed by using wsprintf.
...
start:
stdcall bubble, mas1
mov ebx, (N-1)*2
toStack:
movsx eax, word [mas1+ebx]
push eax
sub ebx, 2
jnb toStack
cinvoke wsprintf, buff, numStr
...
sub ecx, 2
jnz outerLoop
; See no more toStack here!
ret
endp
...
I got this code from the Geeks-for-Geeks site, but there were lots of indentation errors, I changed the code to the following but, when running the code using MASM and DOSBox it's giving no output.
The Output I should get, According to the site I should get 20 but I get nothing, the code is saved as pro.asm, and I'm using DOSBox version 0.74.
For getting the o/p in the DOSBox I did,
mount c c:\8086
c:
ml pro.asm
Code:
;8086 program to convert a 16-bit decimal number to octal
.MODEL SMALL
.STACK 100H
.DATA
d1 dw 16
.CODE
MAIN PROC FAR
MOV ax,#DATA
MOV ds,ax
;load the value stored in variable d1
MOV ax, d1
;convert the value to octal
;print the value
CALL PRINT
;interrupt to exit
MOV AH,4CH
INT 21H
MAIN ENDP
PRINT PROC
;initialize count
MOV cx,0
MOV dx,0
label1: ;if ax is zero
cmp ax,0
je print1
;initialize bx to 8
mov bx, 8
;divide it by 8 to convert it to octal
div bx
;push it in the stack
push dx
;increment the count
inc cx
;set dx to 0
xor dx,dx
jmp label1
print1: ;check if count is greater than zero
cmp cx,0
je exit
;pop the top of stack
pop dx
;add 48 so that it
;represents the ASCII
;value of digits
add dx,48
;interrupt to print a
;character
mov ah,02h
int 21h
;decrease the count
dec cx
jmp print1
exit : ret
PRINT ENDP
END MAIN
The output I'm getting can be seen below
Your code looks okay. Your screenshot shows you have only assembled and linked the code but not actually run it. To run it type:
pro.exe
I have an user input string, which was lowercased and all special characters removed target2 and I want to count how many times each letter appears on the string, and then print the array with 26 letters. However, it prints just a blank line. Is the error when I add to the array? when I print from the array, or both?
If I watch letterArray, it says 1 '\x1' What does that mean?
lettersArray byte 26 dup(0)
countingLetters proc
; clear esi and edi
mov esi, 0
mov edi, 0
charloop
mov al, target2[esi] ; Get a character from the string
cmp al, 97 ; Check if its not a letter
jb printloop ; If bellow, print
sub eax, 97 ; so that 'a' = 0, 'z' = 26.
mov dl, lettersArray[eax]
inc dl
mov lettersArray[eax], dl
inc esi
jmp charloop ; repeat
printloop:
mov bl, lettersArray[edx * type lettersArray]
add bl, 48
push edx
invoke WriteConsoleA, consoleOutHandle, ebx, 4, bytesWritten, 0
pop edx
inc edx
cmp edx, 25 ;Are we done?
ja done ;if yes
jmp printloop ; Repeat
done:
ret
countingLetters endp
This should count the appearances of each letter and print an array with 26 elements, i.e: 00102000000000[etc]
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
I just want too write simple .asm code for TASM that work as for in C++
int t=2;
for(int i=0;i<2;i++)
t=t+(i-1)*7*t;
How can I implement it with TASM?
This will loop from 1 to 100 in 8086 TASM:
.MODEL SMALL
.STACK 100h
.DATA
Finished DB 10, 13, 'Loop x 100 finished. Congratulations! $', 10, 13
.CODE
MAIN PROC
MOV AX, #data ; Required at the start of every program (inside your main procedure, from what I've seen)
MOV DS, AX
MOV CX, 100 ; Set CX to 100
MOV BX, 0 ; Counter (for double-verification, I guess...lol)
StrtLoop: ; When a loop starts, it does CX-- (subtracts 1 from CX)
INC BX ; This does BX++, which increments BX by 1
LOOP StrtLoop ; Go back to StrtLoop label
CMP BX, 100 ; Compare BX to 100...
JE DispMsg ; Jump-if-Equal...CMP BX, 100 sets flags, and if they are set,
; JE will Jump you to DispMsg (to get "congratulations" message).
JMP SkipMsg ; Jump to the SkipMsg label (so you don't see the "congratulations" message).
DispMsg: ; If BX = 100, you JE here.
MOV AH, 09H ; Displays the message stored in the defined byte "Finished"
MOV DX, OFFSET Finished
INT 21H
SkipMsg: ; If BX != 100, you JMP here.
MOV AL, 0h ; Op code to exit to DOS from the assembler.
MOV AH, 4CH
INT 21H
MAIN ENDP
END MAIN
I hope it helps. I did the basic loop, so you can do the other bits of your code (and I don't know C++, lol). Good luck! It's hard, but kind of fun at the same time (at least for me).