I have a question that asks me to merge two arrays with each value being an int
, so 4 bytes long, into one array. The values in the arrays are in order from highest to lowest and so needs to be the new array.
The arrays end with 0 both, and so should the new one.
All 3 of the arrays I get by getting a label to memory, and then the new array needs to be saved in the address of the label mergedArray.
But, the values in the old arrays can appear more than once, while the new array needs to have each value once at most.
The code I wrote seems to work fine while the arrays don't have values appear more than once, but fail once any value appear more than once.
I tried to compare the value I have in the original array to the value I have in the new array, and then skip it if they are the same.
But after running some tests, it seems that adding, or removing that comparison makes no difference to the code.
Here's the code:
.global _start
.section .text
_start:
mov $array1, %rax
mov $array2, %rcx
mov $mergedArray, %r8
xor %r14,%r14
loopcheck: #checks if arrays are finished
movl (%rax), %r9d
movl (%rcx), %r10d
movl (%r8), %r11d
testl %r9d, %r9d
jz rest_of_array2
testl %r10d, %r10d
jz rest_of_array1
loop: #the main loop
cmp %r10d, %r9d
jg add_r9d
jmp add_r10d
add_r9d: #add rax value
cmp %r11d,%r9d
jz remove_current_r9d
mov %r9d, (%r8)
lea 4(%r8), %r14
mov %r14 , %r8
remove_current_r9d: #adv rax
lea 4(%rax), %r14
mov %r14, %rax
jmp loopcheck
add_r10d: #add rcx value
cmp %r11d, %r10d
jz remove_current_r10d
mov %r10d, (%r8)
lea 4(%r8),%r14
mov %r14, %r8
remove_current_r10d: #adv rcx
lea 4(%rcx), %r14
mov %r14, %rcx
jmp loopcheck
rest_of_array2: #adding the rest of array 2 once array 1 is finished
testl %r10d, %r10d
jz end
cmp %r10d,%r11d
jz finish_loop2
movl %r10d, (%r8)
lea 4(%r8),%r14
mov %r14, %r8
finish_loop2:
lea 4(%rcx), %r14
mov %r14 ,%rcx
movl (%rcx), %r10d
movl (%r8), %r11d
jmp rest_of_array2
rest_of_array1: #adding the rest of array 1 once array 2 is finished
testl %r9d,%r9d
jz end
cmp %r9d,%r11d
jz finish_loop1
movl %r9d, (%r8)
lea 4(%r8),%r14
mov %r14, %r8
finish_loop1:
lea 4(%rax),%r14
mov %r14 ,%rax
movl (%rax), %r9d
movl (%r8), %r11d
jmp rest_of_array1
end: #ennd
xor %r14,%r14
mov %r14, (%r8)
I tried to compare the value I have in the original array to the value I have in the new array, and then skip it if they are the same.
But after running some tests, it seems that adding, or removing that comparison makes no difference to the code.
"the value I have in the new array" is not quite what you are using right now in your program! The (thrice-occurring) instruction movl (%r8), %r11d
does read from the memory that is reserved for the destination array, but does so on a part of the array that hasn't been written to yet. In essence, the %R11D register continually gets assigned garbage, or if you're lucky, you get the zeroes that originally populated the .BSS section of the program.
Follow these next steps precisely:
Remove the (thrice-occurring) instruction movl (%r8), %r11d
from the program.
Everywhere you store a value in the destination array, you also need to store a copy of that same value in the %R11D register. So you need to append to the (twice-occurring) instruction movl %r9d, (%r8)
movl %r9d, %r11d
, and to the (twice-occurring) instruction movl %r10d, (%r8)
movl %r10d, %r11d
.
To get started, initialize the %R11D register to 0. You can replace that redundant xor %r14,%r14
by xor %r11d, %r11d
.
end: #ennd xor %r14,%r14 mov %r14, (%r8)
array1 and array2 contain dwords and are terminated by a final 0 which also is a dword.
So, instead of ending mergedArray with a qword 0, have it terminate with a dword 0.
xor %r14d, %r14d
mov %r14d, (%r8)