Simple x86 Assembly Loop- Using PTR - loops

I'm learning x86 assembly and loops are very confusing to me.
For the prompt: "Write a program that uses the variables below and MOV instructions to copy the value from bigEndian to littleEndian, reversing the BYTE order.You will need to use PTR or LABLE to access just a BYTE of the
DWORD element, and use LOOP (set ECX to 4) and ESI and EDI for indirect
addressing."
My code displays 76993356
Should I be using PTR with bigEndian instead of just looping like this?
INCLUDE Irvine32.inc
.data
; declare variables here
bigEndian DWORD 12345678h
littleEndian DWORD 0
.code
main proc
mov ECX, SIZEOF bigEndian
mov EDI, OFFSET littleEndian
mov ESI, OFFSET bigEndian
TOP:
mov al, [ESI]
mov [EDI], al
inc ESI
dec EDI
loop TOP
mov edx, littleEndian
call WriteHex
exit
main ENDP
END main

Related

Allocate a vector of bytes on stack in assembly x86

I try to put on stack the values contained by array_output but every time I print the values from the stack it prints just 0s.
If I try to print the array simple not using the stack it works.
What I do wrong?
stack_alloc:
sub esp, 1
mov al, byte [array_output + ecx]
mov byte [esp], al
add ecx, 1
cmp ebx, ARRAY_OUTPUT_LEN
cmp ebx, ecx
jg stack_alloc
cmp ebx, ARRAY_OUTPUT_LEN
cmp ebx, ecx
jg stack_alloc
You have a typo in your code. The cmp ebx, ARRAY_OUTPUT_LEN instruction should not be comparing but rather loading the EBX register.
You could correct the problem replacing the cmp with a mov but I would propose to simplify your code and just compare the index in ECX to ARRAY_OUTPUT_LEN. This will require choosing the opposite conditional branch and saves from using the additional register EBX:
xor ecx, ecx
stack_alloc:
sub esp, 1
mov al, [array_output + ecx]
mov [esp], al
inc ecx
cmp ecx, ARRAY_OUTPUT_LEN
jb stack_alloc

Assembly x86-32 and some c functions

I never learn C language so it makes me confuse. I just like to know if I did it correctly or where I need to improve. For this code I used assembly x86 32 bit. Thanks
This is what I supposed to do:
Write a procedure with the signature
char *strchar(char *s1, char c1)
that returns a pointer to the first occurrence of the character c1 within the string s1 or, if not found, returns a null.
This is what I came out with:
strchar (char*, char):
push ebp
mov ebp, esp
mov dword ptr [ebp-24], edi
mov EAX , esi
mov BYTE PTR [ebp-28], al
.L5:
mov EAX , dword ptr [ebp-24]
movzx EAX , byte ptr [ EAX ]
test AL, AL
je .L2
mov EAX , dword PTR [ebp-24]
movzx EAX , BYTE PTR [ EAX ]
cmp BYTE PTR [ebp-28], al
jne .L3
mov eax, dword PTR [ebp-24]
jmp .L6
.L3:
add dword PTR [ebp-24], 1
jmp .L5
.L2:
LEA eax, [ebp-9]
MOV DWORD PTR [EBP-8], eax
MOV EAX, DWORD PTR [ebp-8]
.L6:
POP EBP
RET
The lines:
mov dword ptr [ebp-24], edi
mov EAX , esi
mov BYTE PTR [ebp-28], al
assume that a stack frame has been allocated for this function which doesn’t appear true; I think you should have something like:
sub esp, 32
after the
mov ebp,esp
Also, the three lines after L2 seem confused. The only way to get to L2 is if the nil (0) byte is discovered in the string, at which point, the code should return a NULL pointer.
The exit path in the code (L6) leaves eax alone, so all that should be needed is:
L2:
mov eax, 0
It might make debugging easier if you kept the alias up to date; so:
L2:
mov eax, 0
mov [ebp-24], eax
Also, the calling convention used here is a bit odd: the string is passed in edi and the character in esi. Normally, in x86-32, these would both be passed on the stack. This looks like it might have been x86-64 code, converted to x86-32....
A final note; this assembly code looks like the output of a compiler with optimisations disabled. Often, generating the assembly with the optimisations enabled generates easier to understand code. This code, for example, could be much more concisely written as below, without even devolving into weird intel ops:
strchar:
mov edx, esi
mov eax, edi
L:
mov dh, [eax]
test dh, dh
jz null
cmp dh, dl
je done
inc eax
jmp L
null:
mov eax, 0
done:
ret
Here is one with stack overhead
[global strchar]
strchar:
push ebp
mov ebp, esp
mov dl, byte [ebp + 12]
mov ecx, dword [ebp + 8]
xor eax, eax
.loop: mov al, [ecx]
or al, al
jz .exit
cmp al, dl
jz .found
add ecx, 1
jmp .loop
.found: mov eax, ecx
.exit:
leave
ret
Here is one without stack overhead
[global strchar]
strchar:
mov dl, byte [esp + 8]
mov ecx, dword [esp + 4]
xor eax, eax
.loop: mov al, [ecx]
or al, al
jz .exit
cmp al, dl
jz .found
add ecx, 1
jmp .loop
.found: mov eax, ecx
.exit:
ret
These are using the 'cdecl' calling convention. For 'stdcall' change the last 'ret' to 'ret 8'.

How to reverse an array is assembly?

I'm trying to write a simple program that reverses an array. It almost works, well it works for the first half of the array anyway. The term in the middle is always "0" and then it returns to the pattern. For example, if I input: 1,2,3,4,5,6,7,8,9,10, the output will be 10,9,8,7,6,0,6,5,4,3. The order of the program is basically this:
Call to ReverseArray:
INVOKE ReverseArray,
LENGTHOF array, SIZEOF array, TYPE array, OFFSET array
ReverseArray procedure (loops through the array and calls mSwap32):
ReverseArray PROC,
len:DWORD, s:DWORD, increment:DWORD,address:DWORD
mov edx, OFFSET revArray
call WriteString
mov edi, address
mov esi, address
add esi, s
sub esi, TYPE array
mov ecx, len
shr ecx, 1
L2:
mSwap32 edi, esi
add edi, increment
sub esi, increment
loop L2
ret
ReverseArray endp
mSwap32 Macro (is given two addresses to swap):
mSwap32 MACRO address1:REQ, address2:REQ
mov edi, address1
mov esi, address2
mov eax, [esi]
push eax
mov eax, [edi]
mov [esi], eax
pop eax
mov [edi], eax
ENDM
I'm fairly certain that the error is in mSwap32...I'm sure it is some small logical error I'm missing, but no matter how much I toy with it I can not figure it out. ??
it's a WORD array
With this crucial piece of information we can solve the problems. LENGTHOF will be 10 (as before), SIZEOF will now be 20 and TYPE will now be 2.
ReverseArray PROC,
len:DWORD, s:DWORD, increment:DWORD,address:DWORD
mov edx, OFFSET revArray
call WriteString
mov edi, address
mov esi, address
add esi, s
sub esi, increment ;Better not refer to the actual array here!
mov ecx, len
shr ecx, 1
L2:
mSwap32 edi, esi
add edi, increment
sub esi, increment
loop L2
ret
ReverseArray endp
and the macro:
mSwap32 MACRO address1:REQ, address2:REQ
mov edi, address1
mov esi, address2
mov ax, [esi]
push eax
mov ax, [edi]
mov [esi], ax
pop eax
mov [edi], ax
ENDM
Shorter and still using a macro:
mSwap32 MACRO address1:REQ, address2:REQ
mov edi, address1
mov esi, address2
mov ax, [esi]
xchg ax, [edi]
mov [esi], ax
ENDM

What is the difference between mov al, byte ptr [esi] and mov al,[num]

I have some code that works properly, but I want to know the difference between
using mov al, byte ptr [esi] and mov al,[num]. Also why do I need to define the pointer variable to dd instead of define db. Here's the code
.386
.model flat, stdcall
.stack 1000h
Sleep proto arg1:dword
printf proto c arg1:ptr byte, printlist:vararg
.data
array db "hello" ,0
pointerByte dd offset array
fmtmsg1 db "%c",0
.code
public main
main proc
mov esi,pointerByte
mov cl,0
repeat_loop:
push ecx
mov al,byte ptr [esi]
invoke printf,addr fmtmsg1,al
inc esi
pop ecx
inc cl
cmp cl,5
jne repeat_loop
;done
ret
main endp
end main
Given that num is equivalent to the address stored in esi, there is no practical difference between the two.
You need to define the pointer variable with dd (data double) because you are assigning an 32-bit offset. db (data byte) is only for 8-bit assignments. Also, take into consideration that dw (data word) exists.

I am dealing with a possible array in assembly, but I cannot figure out what the starter value is

Size contains the number 86.
var_10= dword ptr -10h
var_C= dword ptr -0Ch
size= dword ptr 8
push ebp
mov ebp, esp
sub esp, 28h
mov eax, [ebp+size]
mov [esp], eax ; size
call _malloc
mov ds:x, eax
mov [ebp+var_C], 0
jmp short loc_804889E
loc_804889E: ~~~~~~~~~~~~~~~~~~~~~
mov eax, [ebp+size]
sub eax, 1
cmp eax, [ebp+var_C]
jg short loc_8048887
loc_8048887: ~~~~~~~~~~~~~~~~~~~~~
mov edx, ds:x
mov eax, [ebp+var_C]
add edx, eax
mov eax, [ebp+var_C]
add eax, 16h
mov [edx], al
add [ebp+var_C], 1
I am having difficulties reversing this portion of a project I am working on. There's a portion of the code where ds:x is moved into edx and is added with var_c and I am unsure where to go with that.
To me the program looks like it calls malloc and then moves that into ds:x and then moves 0 to var_c.
After that it simply subtracts 1 from the size of my pointer array and compares that number to 0, then jumps to a portion where it adds ds:x into edx so it can add eax to edx.
Am I dealing with some sort of array here? What is the first value that's going to go into edx in loc_8048887? Another way this could help would be to see a C equivalent of it... But that would be what I am trying to accomplish and would rather learn the solution through a different means.
Thank you!
In x86 assembly there's no strict distinction between a variable stored in memory and an array in memory. It only depends on how you access the memory region. All you have is code and data. Anyway, I'd say that ds:x is an array as because of this code here:
mov edx, ds:x ; edx = [x]
mov eax, [ebp+var_C] ; eax = something
add edx, eax ; edx = [x] + something
mov eax, [ebp+var_C] ; eax = something
add eax, 16h ; eax = something + 0x16
mov [edx], al ; [[x] + something ] = al . Yes, ds:x is an array!
What is the value of edx in loc_8048887? To find it out you only need some very basic debugging skills. I assume you have gdb at hand, if not, get it ASAP. Then compile the code with debug symbols and link it, then run gdb with the executable, set a code breakpoint at loc_8048887, run the program with r, and finally check the value of edx.
These are the commands you need:
gdb myexecutable
(gdb) b loc_8048887
(gdb) r
(gdb) info registers edx

Resources