Hi I am just doing this for practice before I create a loop that can flip an 3x3 image horizontally or vertically. I am using a variable called ap to store the addresses of the first pixel. I would also like to eventually use another variable called amp to store the mirrored pixel address, and also a register to store the calculated offset of the pixels but for now I put it in manually. No matter what I do the program doesn't swap them. Does anyone have an idea of what is the issue? Thank you for reading.
mov ecx, dword ptr[eax + ecx * 4]
mov ap, ecx //temporary pixel address storage
mov ecx, 0
mov ecx, dword ptr[eax + ecx * 4 + 8] //offset by 8 pixels
mov [ap], ecx
I am using a variable called ap to store the addresses of the first pixel
If the ap variable is suppossed to contain an addresss than you need to use the lea instruction (not the mov instruction).
; For the 1st line EAX is address of image = address of 1st pixel
mov ecx, 0 ;Index to 1st pixel
lea ecx, dword ptr[eax + ecx * 4] ;Address of 1st pixel
mov [ap], ecx
mov ecx, 2 ;Index to 3rd pixel
lea ecx, dword ptr[eax + ecx * 4] ;Address of 3rd pixel
mov [amp], ecx
Now to swap these pixels and thus flipping the image you can write:
mov ecx, [ap]
mov edx, [amp]
mov [ap], edx
mov [amp], ecx
To proces the next lines of the image you could each time add the number of bytes per scanline to the EAX register. For an 3x3 image that's probably 12.
I don't get what this suppose to do:
mov ecx, dword ptr[eax + ecx * 4]
whats in ecx? is it a counter for offset? but you are overriding it each time...
If you'r trying to save the original bit i think that you need to make sure you got the right value in ecx. try
mov ecx, 0
first (you can also xor ecx, ecx it gets the job done and its easier to read)
Related
My goal in this code is to find the smallest number in the list. I used bubble sort method in this case; unfortunately, the code is not giving me the smallest/minimum number. Please take a look, Thanks:
include irvine32.inc
.data
input byte 100 dup(0)
stringinput byte "Enter any string: ",0
totallength byte "The total length is: ",0
minimum byte "The minimum value is: ",0
.code
stringLength proc
push ebp
mov ebp, esp
push ebx
push ecx
mov eax, 0
mov ebx, [ebp+8]
L1:
mov ecx, [ebx] ;you can use ecx, cx, ch, cl
cmp ecx, 0 ;you can use ecx, cx, ch, cl
JE L2
add ebx, 1
add eax, 1
jmp L1
L2:
pop ecx
pop ebx
mov ebp, esp
pop ebp
ret 4
stringLength endp
BubbleSort PROC uses ECX
push edx
xor ecx,ecx
mov ecx, 50
OUTER_LOOP:
push ecx
xor ecx,ecx
mov ecx,14
mov esi, OFFSET input
COMPARE:
xor ebx,ebx
xor edx,edx
mov bl, byte ptr ds:[esi]
mov dl, byte ptr ds:[esi+1]
cmp bl,dl
jg SWAP1
CONTINUE:
add esi,2
loop COMPARE
mov esi, OFFSET input
pop ecx
loop OUTER_LOOP
jmp FINISHED
SWAP1:
xchg bl,dl
mov byte ptr ds:[esi+1],dl
mov byte ptr ds:[esi],bl
jmp CONTINUE
FINISHED:
pop edx
ret 4
BubbleSort ENDP
main proc
call clrscr
mov edx, offset stringinput
call writeString
mov edx, offset input
call writeString
call stringLength
mov edx, offset input
mov ecx, sizeof input
call readstring
call crlf
mov edx,offset totallength
call writestring
call writedec
call crlf
mov edx, offset minimum
call crlf
call writeString
push offset input
call BubbleSort
mov edx, offset input
call writeString
call crlf
exit
main endp
end main
I haven't looked over your code, because sorting is an over complicated method for what you want to do. Not only that, but most of us don't pay too much attention to uncommented code. Just takes to long to figure out what you're trying to do.
Simply iterate through the entire list and start with 255 (FFH) in AL let's say. Each time you come across a number that is smaller than the one in AL, then replace it with that value and then when loop is finished, AL will have the lowest value.
If you need to know where it is in the list, you could maybe use AH which would be the difference between start address and current address. Knowledge of the instruction set is essential as finding the length of the string can be simplified by;
mov di, input ; Point to beginning of buffer
mov cx, -1 ; for a maximum of 65535 characters
xor al, al ; Looking for NULL
rep scasb
neg cx
dec cx ; CX = length of string.
Remember, ES needs to point to #DATA
I am looking for a way to print an integer in assembler (the compiler I am using is NASM on Linux), however, after doing some research, I have not been able to find a truly viable solution. I was able to find a description for a basic algorithm to serve this purpose, and based on that I developed this code:
global _start
section .bss
digit: resb 16
count: resb 16
i: resb 16
section .data
section .text
_start:
mov dword[i], 108eh ; i = 4238
mov dword[count], 1
L01:
mov eax, dword[i]
cdq
mov ecx, 0Ah
div ecx
mov dword[digit], edx
add dword[digit], 30h ; add 48 to digit to make it an ASCII char
call write_digit
inc dword[count]
mov eax, dword[i]
cdq
mov ecx, 0Ah
div ecx
mov dword[i], eax
cmp dword[i], 0Ah
jg L01
add dword[i], 48 ; add 48 to i to make it an ASCII char
mov eax, 4 ; system call #4 = sys_write
mov ebx, 1 ; file descriptor 1 = stdout
mov ecx, i ; store *address* of i into ecx
mov edx, 16 ; byte size of 16
int 80h
jmp exit
exit:
mov eax, 01h ; exit()
xor ebx, ebx ; errno
int 80h
write_digit:
mov eax, 4 ; system call #4 = sys_write
mov ebx, 1 ; file descriptor 1 = stdout
mov ecx, digit ; store *address* of digit into ecx
mov edx, 16 ; byte size of 16
int 80h
ret
C# version of what I want to achieve (for clarity):
static string int2string(int i)
{
Stack<char> stack = new Stack<char>();
string s = "";
do
{
stack.Push((char)((i % 10) + 48));
i = i / 10;
} while (i > 10);
stack.Push((char)(i + 48));
foreach (char c in stack)
{
s += c;
}
return s;
}
The issue is that it outputs the characters in reverse, so for 4238, the output is 8324. At first, I thought that I could use the x86 stack to solve this problem, push the digits in, and pop them out and print them at the end, however when I tried implementing that feature, it flopped and I could no longer get an output.
As a result, I am a little bit perplexed about how I can implement a stack in to this algorithm in order to accomplish my goal, aka printing an integer. I would also be interested in a simpler/better solution if one is available (as it's one of my first assembler programs).
One approach is to use recursion. In this case you divide the number by 10 (getting a quotient and a remainder) and then call yourself with the quotient as the number to display; and then display the digit corresponding to the remainder.
An example of this would be:
;Input
; eax = number to display
section .data
const10: dd 10
section .text
printNumber:
push eax
push edx
xor edx,edx ;edx:eax = number
div dword [const10] ;eax = quotient, edx = remainder
test eax,eax ;Is quotient zero?
je .l1 ; yes, don't display it
call printNumber ;Display the quotient
.l1:
lea eax,[edx+'0']
call printCharacter ;Display the remainder
pop edx
pop eax
ret
Another approach is to avoid recursion by changing the divisor. An example of this would be:
;Input
; eax = number to display
section .data
divisorTable:
dd 1000000000
dd 100000000
dd 10000000
dd 1000000
dd 100000
dd 10000
dd 1000
dd 100
dd 10
dd 1
dd 0
section .text
printNumber:
push eax
push ebx
push edx
mov ebx,divisorTable
.nextDigit:
xor edx,edx ;edx:eax = number
div dword [ebx] ;eax = quotient, edx = remainder
add eax,'0'
call printCharacter ;Display the quotient
mov eax,edx ;eax = remainder
add ebx,4 ;ebx = address of next divisor
cmp dword [ebx],0 ;Have all divisors been done?
jne .nextDigit
pop edx
pop ebx
pop eax
ret
This example doesn't suppress leading zeros, but that would be easy to add.
I think that maybe implementing a stack is not the best way to do this (and I really think you could figure out how to do that, saying as how pop is just a mov and a decrement of sp, so you can really set up a stack anywhere you like by just allocating memory for it and setting one of your registers as your new 'stack pointer').
I think this code could be made clearer and more modular if you actually allocated memory for a c-style null delimited string, then create a function to convert the int to string, by the same algorithm you use, then pass the result to another function capable of printing those strings. It will avoid some of the spaghetti code syndrome you are suffering from, and fix your problem to boot. If you want me to demonstrate, just ask, but if you wrote the thing above, I think you can figure out how with the more split up process.
; Input
; EAX = pointer to the int to convert
; EDI = address of the result
; Output:
; None
int_to_string:
xor ebx, ebx ; clear the ebx, I will use as counter for stack pushes
.push_chars:
xor edx, edx ; clear edx
mov ecx, 10 ; ecx is divisor, devide by 10
div ecx ; devide edx by ecx, result in eax remainder in edx
add edx, 0x30 ; add 0x30 to edx convert int => ascii
push edx ; push result to stack
inc ebx ; increment my stack push counter
test eax, eax ; is eax 0?
jnz .push_chars ; if eax not 0 repeat
.pop_chars:
pop eax ; pop result from stack into eax
stosb ; store contents of eax in at the address of num which is in EDI
dec ebx ; decrement my stack push counter
cmp ebx, 0 ; check if stack push counter is 0
jg .pop_chars ; not 0 repeat
mov eax, 0x0a
stosb ; add line feed
ret ; return to main
; eax = number to stringify/output
; edi = location of buffer
intToString:
push edx
push ecx
push edi
push ebp
mov ebp, esp
mov ecx, 10
.pushDigits:
xor edx, edx ; zero-extend eax
div ecx ; divide by 10; now edx = next digit
add edx, 30h ; decimal value + 30h => ascii digit
push edx ; push the whole dword, cause that's how x86 rolls
test eax, eax ; leading zeros suck
jnz .pushDigits
.popDigits:
pop eax
stosb ; don't write the whole dword, just the low byte
cmp esp, ebp ; if esp==ebp, we've popped all the digits
jne .popDigits
xor eax, eax ; add trailing nul
stosb
mov eax, edi
pop ebp
pop edi
pop ecx
pop edx
sub eax, edi ; return number of bytes written
ret
If I do step through the debugger in Ollydbg I see
MOV EAX,DWORD PTR DS:[ESI+EBP*8]
and register ESI = 0040855C and EBP = 00000000.
My problem is I dont know 2 register * 8
MOV EAX,DWORD PTR DS:[ESI+EBP*8]
MOV - move
EAX - to EAX (generally this will be a value you just calculated)
DWORD PTR - from the value pointed at by
[DS: - in the data segment]
[ESI+EBP*8] - ESI plus 8 times EBP.
Move the value in EAX into the address pointed at by ESI + EBP*8 (ESI plus 8 times EBP, it means exactly how it's written)
This is probably being used to load data from an array, where the 8 is there to scale up the counter (which is EBP) to the size of the thing being stored (8 bytes), and ESI contains the address of the start of the array. So if EBP is zero, you store the data in ESI+0, if EBP=1, you end up storing at ESI+8, etc.
In normal INTEL syntax this instruction moves a value from memory into EAX.
MOV EAX,DWORD PTR DS:[ESI+EBP*8]
It is usually used to extract a value from an array.
The array is situated in memory at DS:ESI.
The elements are indexed through EBP.
The scale of 8 means that every element is 64 bit long and this instruction only reads the low dword.
My problem is an academic task I've been asigned:
What will be the content of edx after this fragment of a program:
linie dd 421, 422, 443
dd 442, 444, 427, 432
----------------
mov esi, (OFFSET linie)+4
mov ebx, 4
mov edx, [ebx][esi]
I have two questions:
What is the meaning of mov edx, [ebx][esi]?
Why is there 000001bb in my edx after debugging the program?
Firstly, mov edx, [ebx] [esi] means the same as mov edx, [ebx + esi] - it refers to the memory cell of adress which is the sum
of the ebx and esi registers.
There will be 443 (1bb in hex)in your edx register after completing the program. First, let's notice that in linie you define dwords
which are 32-bit words.
mov esi, (OFFSET linie)+4 ;sends the adress of the begining of the linie
;area plus 4 bytes(32 bits)
; the esi will point to 422 in the linie array
mov ebx, 4 ;simple asigning 4 to ebx
mov edx, [ebx][esi] ;move the content of a memory cell of
;adress 4+ the adress of 422
; in other words - move the third element of the
;linie array to edx.
mov esi, (OFFSET linie)+4
mov ebx, 4
mov edx, [ebx][esi]
This will read the value from [ebx + esi], i.e. [linie+4+4]. That corresponds to the third element of linie (since each element is DWORD, which on x86 is 4 bytes), and that element is 443 decimal == 0x1bb hexadecimal.
Suppose that I have a 2D array, and I want to check whether one slot is adjacent and touching with another.
Suppose that the coordinates are in the 4-byte variables: OneX, OneY, TwoX, TwoY.
The solution I had for a while was that if you have the differences OneX - OneY and TwoX - TwoY and add them, if the result is either 1 or -1, then yes, the slots are adjacent and touching.
mov EBX,[oneX]
sub EBX,[oneY]
mov ECX,[twoX]
sub ECX,[twoY]
add EBX,ECX
; Compare EBX with 1 or -1.......
This almost works. But no - given a format (x,y), take: (3,3) and (0,1). They're clearly not adjacent nor touching, but the function will say they are.
The question at Get adjacent elements in a two-dimensional array? is somewhat useful, but it focuses on finding all adjacent matches, whereas I want to check for two specific slots instead.
The structure of my array is like this:
map: dd 'a','b','c','d' ; Double words just to make my life easier
Which is interpreted like
a b
c d
It's a square map.
There is no reason to Add them! And you are also substracting incorrect variables :).
You have to have two conditions OneX - TwoX and OneY - TwoY : both has to be 1, 0 or -1.
For example One is [4,5] and Two is [5,5] >= OneX - TwoX = -1 and OneY - TwoY = 0 => it is adjanced tile.
EDIT : For non-diagonal, there are two approaches :
a)One of condition must be 0 and the other one must be 1 or -1
b)Adding absolute value of OneX - TwoX and absolute value of OneY - TwoY must be 1
Here is some practical code, based on #libik answer:
Optimized for speed:
; eax = OneX-TwoX; ecx = OneY-TwoY
mov eax, [OneX]
mov ecx, [OneY]
sub eax, [TwoX]
sub ecx, [TwoY]
; eax = abs(eax); ecx=abs(ecx)
mov ebx, eax
mov edx, ecx
sar ebx, 31
sar edx, 31
xor eax, ebx
xor ecx, edx
sub eax, ebx
sub ecx, edx
; eax=abs(delta1)+abs(delta2); if eax = 1, jump to where needed
add eax, ecx
dec eax
lz .adjacent
Optimized for size:
; eax = abs(OneX-TwoX); ecx = abs(OneY-TwoY)
mov eax, [OneX]
mov ecx, [OneY]
sub eax, [TwoX]
jns #f
neg eax
##:
sub ecx, [TwoY]
jns #f
neg ecx
##:
; eax=abs(delta1)+abs(delta2); if eax = 1, jump to where needed
add eax, ecx
dec eax
lz .adjacent
Including diagonal cases
Replace add eax, ecx with or eax, ecx