how do I swap the elements of 2 arrays of different types of the same length? - arrays

Not sure if I need a third array to temporarily store values in order to swap contents of arrayA and arrayB. I am a student learning assembly for the first time so please keep it simple.
.386
.model flat,stdcall ; memory system
.stack 4096 ; declare stack memory size 4kb
ExitProcess proto,dwExitCode:dword
.data
arrayA byte 01d, 04d, 02d ; 8bits
arrayB word 02d, 05d, 05d ; 16bits
.code
main proc
mov EAX, 0
mov EBX, 0
mov ECX, 3
mov EDX, 0
L1:
movzx bx, arrayA[ebx]
mov ax, arrayB[ebx]
xchg arrayA[ebx], al
xchg arrayB[ebx], bx
inc ebx
loop L1
invoke ExitProcess,0
main endp
end main

Related

Reverse the array in Assembly Language 80X86

Write an assembly program that defines the following array 10 25 56 80 3 , then create procedure reverse to display the array in reverse.
I can only get the size of the array. I tried to use push/pop.
Thank you!
.586
.MODEL FLAT
INCLUDE io.h
.stack 4096
.DATA
array1 DWORD 10,25,56,80,3 DUP (?)
size1 DWORD 5
outputLbl BYTE "The reverse is", 0
result BYTE 11 DUP (?), 0
.CODE
_MainProc PROC
mov eax,5
lea ebx,array1 ;get address
call reverse
dtoa result, eax
output outputLbl, result
_MainProc ENDP
reverse PROC
pushad
mov ecx, (5)/2
mov esi,0
mov edi,((5)-1)
L1:
mov eax, array1[esi*4]
mov ebx, array1[edi*4]
mov array1[esi*4], ebx
mov array1[edi*4], eax
loop L1
popad
ret
reverse ENDP
END

Array that copies its contents to another array backwards is not working properly

When I run through this code it is my understanding that arrayA will be copied to arrayB backwards. So when I try to view what's in arrayB[1], it should be 6, but it's coming out to 0.
I know this code is inefficient. This is only an exercise to use the operators offset, sizeof and lengthof to avoid direct memory access and any use of constants. I'm a student, so the simplest fix is the best fix.
.386
.model flat,stdcall ; memory system
.stack 4096 ; declare stack memory size 4kb
ExitProcess proto,dwExitCode:dword
.data
arrayA word 01d, 05d, 06d, 02d
arrayB word 00d, 00d, 00d, 00d
.code
main proc
mov eax, 0
mov esi, offset arrayA
mov ecx, sizeof arrayA
mov ebx, lengthof arrayB
sub ebx, 1
L1:
mov ax, [esi]
add esi, type arrayA
mov arrayB[ebx], ax
sub ebx, 1
sub ecx, type arrayA
cmp ecx, 0
jne L1
mov ax, arrayB[1]
invoke ExitProcess,0
main endp
end main

Assembly How should I increment the array if I want to switch values?

This is being compiled on Visual Studios 2015 with Kip Irvine.
The code is supposed to switch the 1st element with the 2nd element and the 3rd element with the 4th element and so on. It switches the values forward instead of just switching the two values. I added the index register with 2 to skip the 2nd element since it should not be switched. Is there something I am missing? Am I supposed to increment the array index differently or am I putting the wrong values in the wrong registers? Thanks in advance! Please don't just give me the answer.
The output is
Dump of offset 00AD6880
00020000 00050000 00090000 0000000A 0000000C
INCLUDE Irvine32.inc
.data
dwarray dword 0,2,5,9,10,12
.code
main proc
mov ebx, OFFSET dwarray
mov ecx, LENGTHOF dwarray
L1: cmp ebx, ecx
mov eax, [ebx]
mov edx, [ebx+1]
mov [ebx+1], eax
mov [ebx], edx
add ebx, 2
loop L1
; The four instructions below are fixed, the only variable is the name of the array
mov esi,OFFSET dwarray
mov ecx,LENGTHOF dwarray
mov ebx,TYPE dwarray
call DumpMem
call WaitMsg
exit
main ENDP
END main
Your array elements are dword, double word, that means 4 bytes. So, in order to point to the elements you need to increase your pointer by 4 :
dwarray dword 0,2,5,9,10,12
.code
main proc
mov ebx, OFFSET dwarray
mov ecx, 3 ◄■■■ THE ARRAY CONTAINS 6 ELEMENTS, BUT THEY ARE PROCESSED
IN PAIRS, SO THE LOOP SHOULD REPEAT HALF 6 (3).
L1: ;cmp ebx, ecx ◄■■■ UNNECESSARY?
mov eax, [ebx]
mov edx, [ebx+4] ◄■■■ THE NEXT ELEMENT IS 4 BYTES AWAY.
mov [ebx+4], eax ◄■■■ AGAIN, THE NEXT ELEMENT IS 4 BYTES.
mov [ebx], edx
add ebx, 8 ◄■■■ INCREASE BY 8 (THE SIZE OF 2 ELEMENTS PROCESSED).
loop L1

Looping backwards in Assembly x86

When you are looping backwards in Assembly x86, what is currently happening in the memory (Can you try to be visual, thanks)? The following code is what I am currently wondering about:
INCLUDE Irvine32.inc
.data
arrayb byte 1,2,3,4,5,6 ;6-7 bytes
len dword lengthof arrayb
space byte " ",0
x dword 3
.code
main PROC
mov edx,offset space
mov eax,0 ; clear ecx of garbage
mov ecx, len
mov esi,offset arrayb ; start of the array's memory
add esi,len ;This causes the array value to start at 6
dec esi ; esi goes from esi+5,esi+4,...,esi
myloop2:
mov al,[esi]
call writedec
call writestring
dec esi
loop myloop2
call crlf
In particular, why did I have to add 1 to esi? When you add 1 to the high speed memory transfer register esi, it seems that it causes the array value to start at 6. Why is that?Thank you.

Arrays in MASM Assembly (very confused beginner)

I have a pretty basic question:
How do you populate arrays in assembly? In high level programming languages you can use a for-loop to set a value to each index, but I'm not sure of how to accomplish the same thing assembly. I know this is wrong, but this is what I have:
ExitProcess PROTO
.data
warray WORD 1,2,3,4
darray DWORD ?
.code
main PROC
mov edi, OFFSET warray
mov esi, OFFSET darray
mov ecx, LENGTHOF warray
L1:
mov ax, [edi] ;i want to move a number from warray to ax
movzx esi,ax ;i want to move that number into darray...
add edi, TYPE warray ;this points to the next number?
loop L1
call ExitProcess
main ENDP
END
Each time the loop runs, ax will be overwritten with the value of the array's index, right? Instead how do I populate darray with the array elements from warray? Any help would be very much appreciated...I'm pretty confused.
There are more than one way to populate an array and your code is almost working. One way is to use counter in the indirect address so you don't have to modify destination and source array pointers each loop:
ExitProcess PROTO
.data
warray WORD 1,2,3,4
darray DWORD 4 dup (?) ; 4 elements
.code
main PROC
mov edi, OFFSET warray
mov esi, OFFSET darray
xor ecx, ecx ; clear counter
L1:
mov ax, [edi + ecx * 2] ; get number from warray
movzx [esi + ecx * 4], ax ; move number to darray
inc ecx ; increment counter
cmp ecx, LENGTHOF warray
jne L1
call ExitProcess
main ENDP
END
Of course this code could be modified to fill the array backwards to possibly save couple of bytes like you probably meant to do in your original code. Here is another way that has more compact loop:
ExitProcess PROTO
.data
warray WORD 1,2,3,4
darray DWORD 4 dup (?) ; 4 elements
.code
main PROC
mov edi, OFFSET warray
mov esi, OFFSET darray
mov ecx, LENGTHOF warray - 1 ; start from end of array
L1:
mov ax, [edi + ecx * 2] ; get number from warray
movzx [esi + ecx * 4], ax ; move number to darray
loop L1
; get and set element zero separately because loop terminates on ecx = 0:
mov ax, [edi]
movzx [esi], ax
call ExitProcess
main ENDP
END
You should also note that when working with arrays of the same type you can do simple copy very efficiently using repeat prefix with instructions like MOVSD:
ExitProcess PROTO
.data
array1 DWORD 1,2,3,4
array2 DWORD 4 dup (?)
.code
main PROC
mov esi, OFFSET array1 ; source pointer in esi
mov edi, OFFSET array2 ; destination in edi
mov ecx, LENGTHOF array1 ; number of dwords to copy
cld ; clear direction flag so that pointers are increasing
rep movsd ; copy ecx dwords
call ExitProcess
main ENDP
END
You're probably not "supposed to know" this, but anyway, there were (way back when) an instruction and an instruction prefix that were made to do exactly this.
Take a look here at this Microsoft page: HERE (click on it)
On that page scroll down until you find this phrase...
"...These instructions are remnants of the x86's CISC heritage and in recent processors are actually slower than the equivalent instructions written out the long way...."
What you do is...
Put the size of the array in Ecx
Point Edi at the start of the arry
Use the appropriate string instruction to populate it
The syntax (Masm/Tasm/etc.) will probably look something like this...
Mov Ecx, The_Length_Of_The_Array ;Figure this out somehow
Lea Edi, The_Target_You_Want_To_Fill ;Define this somewhere
Now, if you want to copy from one place to another, do this...
Lea Esi, The_Source_You_Want_To_Copy ;Whatever, define it
Cld ;This is the direction flag, make it inc
Rep Movsb ;Movsb means move byte for byte
Now, if you want to stuff the same value in each byte in the arrray do this...
Mov AL, The_Value_You_Want_To_Stuff ;Define this to your liking
Cld ;This is the direction flag, make it inc
Rep Stosb ;Stosb means store AL into each byte
Again, these instructions are, for reasons others will elucidate, not cool anymore and if you use them you will get cooties or something.
There are also string instructions for comparison, "Scanning", "Loading", and so on. They were once quite useful (and still are, but the "modern" gang today won't admit it) particularly with the Rep prefix added to them.
If this helps, but you need more detail, feel free to ask.

Resources