I'm trying to pass an array of 4-byte integers from C to 32-bit nasm in linux. The function call passes a pointer to the first integer and the length in an integer value in that order. The C-program reads a list of numbers from a file. I've verified that the array is populating correctly.
When I run the following code I get consistent, large values. Each value is the same as the last and none were in the original array.
The relevant nasm code is as follows:
_sumAndPrintList:
push ebp
mov ebp, esp
sub esp, 16
push ebx
push ecx
push edx
push edi
push esi
mov ebx, [ebp + 8] ;Pointer to start of list
mov ecx, [ebp + 12] ;Size of list
push ebx
push ecx
push header ;This is a string and prints correctly
call printf
add esp, 4
pop ecx
pop ebx
xor edi, edi ;counter
xor esi, esi ;running total
printLoop:
cmp edi, ecx ;check if at end of list
je endPrintLoop
add esi, [ebx] ;add value in ebx to esi
mov [value], ebx ;move value in array to value
mov [total], esi ;put esi in total
push ebx
push ecx
push edi
push esi
push total
push value
push printNums ;string that prints the value and then the total
call printf
add esp, 12
pop esi
pop edi
pop ecx
pop ebx
add ebx, dword 1
inc edi
jmp printLoop
Everything prints correctly, just the values are wrong and the total is wrong. I'm fairly new to assembly, so if I've included too much or too little or you have questions, feel free to ask/let me know.
Related
I have managed to successfully sort my array in descending order, but I'm a bit confused about how to sort it into ascending order as well.
I basically want to sort my array into ascending order as well, but I'm kind of stuck. I don't know if I'm overthinking it or not, but I've run into a big roadblock for such a simple problem.
Here's what I have coded for sorting my array of random numbers into descending order:
"""
sortList PROC
push ebp
mov ebp, esp
mov ecx, [ebp + 8]
mov esi, [ebp + 12]
dec ecx
outer_loop:
mov eax, [esi]
mov edx, esi
push ecx
inner_loop:
mov ebx, [esi + 4]
mov eax, [edx]
cmp eax, ebx
jge do_not_swap
;Else, push parameters and swap
add esi, 4
push esi
push edx
push ecx
call exchange
sub esi, 4
do_not_swap:
add esi, 4
loop inner_loop
;End the inner loop and restore outer loop stuff
pop ecx
mov esi, edx
add esi, 4
loop outer_loop
pop ebp
ret 8
sortList ENDP
"""
Any help is greatly appreciated!
Thanks so much for your time.
jge do_not_swap
The jge instruction means JumpIfGreaterOrEqual.
Reversing the sort order is a simple matter of using jle which stands for JumpIfLessOrEqual. That is if the rest of the code works fine like you're saying...
A 1 character change, what great value for your money!
I have to sort an array in descending order using parameters on the stack to an array and an array size. I passed the size by value at ebp+12 and the array by reference at ebp+8.
I know the code is kind of all over the place, but I'm just trying to get to something that works and I can try to clean it up from there.
I've been debugging and it seems to iterate through as I want it to, but my array isn't being sorted. I've been banging my head against this for hours, so any guidance would be greatly appreciated.
The pseudo-code algorithm I'm trying to follow is:
for(k=0, k<arrlength-1,k++)
I=K
for(J=k+1,J<arrlength,J++)
if(arr[j]>arr[i])
I=J
xchg(arr[k], arr[i])
And this is my attempt to implement it in x86 assembly:
;------------------------------------------------
sortlist PROC
;Sorts an array of specified size into descending order
;Receives: DWORD request value, address of an array
;Returns: array of size request, sorted in descending order
;------------------------------------------------
.data
first DWORD ?
next DWORD ?
.code
push ebp
mov ebp, esp
mov ecx, [ebp+12]
mov edi, [ebp+8]
mov eax, 0
mov ebx, 0
mov edx, 0
mov esi, 0
dec ecx ;loop for array length - 1
L1:
add edi, ebx ;ebx = 0 first loop, 4 all remaining loops
mov eax, [edi] ;get the value of the first element
mov first, edi ;store address of first element in first
mov next, edi
push ecx
push edi
L2:
add edi, 4 ;move to next element in array
mov edx, [edi] ;set value of next element to edx
cmp [next], edx ;compare element to next element
jg nxt
mov next, edi ;If less than, move address of greater to next
nxt:
loop L2
mov eax,[next] ;move values pointed to by 1st & next to regs
mov ebx,[first]
mov [first],eax ;move values(swapped) to addresses
mov [next],ebx
mov ebx,4
pop edi
pop ecx
loop L1
pop ebp
ret 8
sortlist ENDP
Having trouble using a string array and getting each character from it and adding a 1 to a frequency table of the corresponding ascii index (frequency table is indexed by ascii value): Example, get character 'a' then add 1 to the frequency table of index of the array ['a']. I was getting segmentation errors and now getting error: invalid combination of opcode and operands, talking about mov ax, al
Any questions about the parameters of the problem please ask. I have working on this for hours and could really use another pair of eyes to check what I am doing wrong (syntax/concept if you see one) Please help.
Update: I have got it print stuff out, so I think it is "working"; however I am now trying to print the characters that each array index corresponds. It won't print the character of the array that I am pointing to (it prints literally nothing for the character).
Latest update: I got it to work. changed some of the code under the label .loopa and now it works fine! :)
Code below:
SECTION .data ; Data section, initialized variables
array5: db "Hello, world...", 0
array5Len: equ $-array5-1
asoutput: db "%s", 0 ; string output
newline: db "", 10, 0 ; format for a new line
acoutput: db "%c: ", 0 ; output format for character output
SECTION .bss ; BSS, uninitialized variables
arrayq: resd 128 ; frequency array of the first 127 ascii values initialized to 0 (none have been counted yet)
SECTION .text
global main ; the standard gcc entry point
main: ; the program label for the entry point
push ebp ; set up stack frame
mov ebp,esp
mov esi, array5
mov edi, 0
mov ebx, arrayq
mov ecx, array5Len
; get each character of array5 and add 1 to the frequency table of the corresponding ascii value (which the arrayq is indexed by ascii value).
.loopf:
xor eax, eax
mov al, [esi]
;mov ax, [esi]
;mov ax, al
;mov cx, ax
add edi, eax
mov ebx, 1
add [arrayq+4*edi], ebx
mov edi, 0
add esi, 1
loop .loopf
push dword array2
push dword asoutput
call printf
add esp, 8
push dword newline
call printf
add esp, 4
;pop ebx
mov ebx, arrayq
mov ecx, 128 ; size of arrayq
mov esi, 0 ;start at beginning
.loopa:
mov eax, 0
cmp [ebx+esi], eax
je .skip
mov eax, esi
push ebx
push ecx
mov ebx, 4
cdq
div ebx
push eax
push dword acoutput
call printf
add esp, 8
pop ecx
pop ebx
push ebx
push ecx ; make sure to put ecx (counter) on stack so we don't lose it when calling printf)
push dword [ebx + esi] ; put the value of the array at this (esi) index on the stack to be used by printf
push dword aoutput ; put the array output format on the stack for printf to use
call printf ; call the printf command
add esp, 8 ; add 4 bytes * 2
pop ecx ; get ecx back
pop ebx
push ebx
push ecx
push dword newline
call printf
add esp, 4
pop ecx
pop ebx
.skip:
add esi, 4
loop .loopa
.end:
mov esp, ebp ; takedown stack frame
pop ebp ; same as "leave" op
Changed code under .loopa label to make it print the character the index is corresponding to:
.loopa:
mov eax, 0
cmp [ebx+esi], eax
je .skip
mov eax, esi
push ebx
push ecx
mov ebx, 4
cdq
div ebx
push eax
push dword acoutput
call printf
add esp, 8
pop ecx
pop ebx
My task here is to add a code that sorts the array with insertion sort.
'printf' function prints a string
printArray prints the array
For some reason the array doesn't get sorted, and i cant find the reason why.
Help will be appreciated.
main:
push MSG ; print welcome message
call printf
add esp,4 ; clean the stack
call printArray ;print the unsorted array
;;;;;;;;;;add code here;;;;;;;;;;
mov eax,1
loop1:
mov ebx, array
add ebx, eax
loop2:
mov esi, ebx
dec esi
mov esi, [esi] ;esi holds the value before what ebx points to
cmp [ebx], esi
ja endLoop2
mov edx, esi
mov esi, ebx
dec esi
mov ecx, [ebx]
mov [esi], ecx
mov [ebx], edx
dec ebx
cmp ebx, array
ja loop2
endLoop2:
inc eax
cmp eax, 11
jbe loop1
;;;;;;;end of your code;;;;;;;;;;;;;;
call printArray
mov eax, 1 ;exit system call
int 0x80
If your array is full of 1 byte values, use movb instead of mov when loading and storing to memory.
I have the following assembly code:
; File: strrev.asm
; A subroutine called from C programs.
; Parameters: string A
; Result: String is reversed and returned.
SECTION .text
global strrev
_strrev: nop
strrev:
push ebp
mov ebp, esp
; registers ebx,esi, and edi must be saved if used
push ebx
push edi
xor esi, esi
xor eax, eax
mov ecx, [ebp+8] ; load the start of the array into ecx
jecxz end ; jump if [ecx] is zero
mov edi, ecx
reverseLoop:
cmp byte[edi], 0
je reverseLoop_1
inc edi
inc eax
jmp reverseLoop
reverseLoop_1:
mov esi, edi ;move end of array into esi
mov edi, ecx ;reset start of array to edi
reverseLoop_2:
mov al, [esi]
mov bl, [edi]
mov [esi], bl
mov [edi], al
inc edi
dec esi
dec eax
jnz reverseLoop_2
end:
pop edi ; restore registers
pop ebx
mov esp, ebp ; take down stack frame
pop ebp
ret
Which works fine until you start looping through reverseLoop_2. Using gdb, eax is listed as being 11, which it should be (this is the length of the string I passed in through a separate c program). This is show in the debugger as:
Breakpoint 2, reverseLoop_2 () at strrev.asm:40
40 mov al, [esi]
(gdb) display $eax
1: $eax = 11
However, if I step through the program to the next line, it resets to 0.
(gdb) next
41 mov bl, [edi]
1: $eax = 0
I need eax to be preserved since its the one keeping track of how many times reverseLoop_2 needs to loop. Why is it resetting to 0 after the call to mov?
If you're using eax as a loop counter, you shouldn't write to it inside the loop :
reverseLoop_2:
mov al, [esi]
Remember that al is the least significant byte of eax :
I think this should work.
mov eax, address of your string
push esi
push edi
mov edi, eax
mov esi, eax
; find end of string
sub ecx, ecx
not ecx
sub al, al
cld
repne scasb
; points to the byte after '0x00'
dec edi
dec edi
; main loop will swap the first with the last byte
; and increase/decrease the pointer until the cross each other
_loop:
cmp esi, edi ; if both pointers meet, we are done
jg _done
mov al, [edi]
mov bl, [esi]
mov [esi], al
mov [edi], bl
inc esi
dec edi
jmp _loop
_done:
pop edi
pop esi