The given logical segment
I1 db ? I2 db ? I3 db ? A1 dw 5 dup (6 dup (0fh,4 dup (0))) Data1 ends
- Create a segment of codes (for example, with the name Code1), in which to implement the following task: replace all words of the three-dimensional array A1 with values 0fh with the sum of of the following (by offset in the segment) 5 words by using the indices I1,I2,I3 (the values located at addresses I1,I2,I3).
- Create another logical data segment (for example, named Data2), in which set the directive A2 dw 5 dup (6 dup (0fh,4 dup (0)))
- Create another logical segment of codes (for example, with the name Code2), in which the task of step 1 is performed using chain commands to search for the value 0fh. After calculation, compare the values in arrays A1 and A2. Ensure unconditional transfer of control from segment Code1 to segment Code2 by using indirect intersegment control transfer.
;for MASM 5.00 translator ;for DOS .386 .MODEL flat ; for MASM 5.00
I can't understand the logic in this task in assembly code.
My code:
.386
Data1 segment
I1 db ?
I2 db ?
I3 db ?
A1 dw 5 dup (6 dup (0fh,4 dup (0)))
Data1 ends
Data2 segment
A2 dw 5 dup (6 dup (0fh,4 dup (0)))
Data2 ends
Code1 segment use16
assume cs:Code1, ds:Data1
start:
mov [I1], 0
mov [I2], 0
mov [I3], 0
mov ax, DATA1
mov ds, ax
L1:
L2:
L3:
movzx ax, byte ptr [I1]
imul bx, ax, 6*5*2
movzx ax, byte ptr [I2]
imul ecx, ax, 5*2
xor esi,esi
movzx ax, byte ptr [I3]
mov si, ax
lea di, [ecx + esi*2]
cmp A1[bx+di],0fh
jne NEXT
mov ax,0
add ax,[A1+bx+di+2]
add ax,[A1+bx+di+4]
add ax,[A1+bx+di+6]
add ax,[A1+bx+di+8]
add ax,[A1+bx+di+10]
mov [A1+bx+di],ax
NEXT:
inc I3
cmp I3, 5
jle L3
mov I3, 0
inc I2
cmp I2, 6
jle L2
mov I2, 0
inc I1
cmp I1, 5
jle L1
jmp far ptr start2
Code1 ends
Code2 segment use16
assume cs:Code2, ds:Data1, es:Data2
start2:
mov ax,data1
mov ds,ax
mov ax,data2
mov es,ax
mov cx, 150d
mov di, OFFSET A2
mov ax, 0fh
cld
L:
repnz scasw
sub di, 2
xor dx,dx
add dx,[A2+di+2]
add dx,[A2+di+4]
add dx,[A2+di+6]
add dx,[A2+di+8]
add dx,[A2+di+10]
mov [A2+di],dx
add di, 2
dec cx
cmp cx,0
jg L
mov si,OFFSET A1
mov di,OFFSET A2
cld
repz cmpsw
sub si, 2
sub di, 2
mov bx,A1[si]
mov dx,A2[di]
mov ax, bx
sub ax, dx
mov ax,4c00h
int 21h
Code2 ENDS
end start2
The data
To me at least, this sounds like you're not supposed to care about reading memory beyond the array. And that is how you have solved it too. I mention this because it will influence the outcome from comparing both arrays (A1 and A2); if the garbage that is in memory after the arrays is any different, then the
repe cmpswcould be producing the wrong result.I'm assuming these data segments are 16-byte aligned, and with no guarantee about the padding at the end. I would suggest the following:
The first method
Your triple nested loops are doing too many iterations! When there are 5 elements in the row, the zero-based index in the I3 variable can range from 0 to 4. With a pair of instructions like
cmp I3, 5jle L3, you are allowing the invalid index 5 to be used. The same error is present for the other indexes.Where do you think that the CPU will store these zero bytes if you don't set up the DS segment register before these
movinstructions that depend on DS are used?Below is my rewrite of these nested loops. I have refrained from repeating the same calculations over and over again in the most inner loop, and I have chosen to use 8086 code only. I know that you can use x86 instructions in real address mode, but what I don't like is the ugly mix of 16-bit and 32-bit registers that you were using for no good reason:
The second method
When this
repne scaswinstruction stops because the count got exhausted, you must not start adding 5 subsequent words. You must exit from your L loop.When this
repne scaswinstruction stops because it found the value 15, the DI register points to behind the find and the CX register contains the number of remaining items. It is wrong to usedec cxat the bottom of your loop!These instructions are adding the address of the A2 array twice! Once through the initialization of DI with
mov di, offset A2and a second time through the mention of[A2+ ...in the addressing mode.Below is my rewrite with corrections applied. Do note that it is not necessary to first subtract 2 from DI, and later add 2 to DI. It is much better to play with the offsets a bit. Offsets can be negative too, as in
mov es:[di-2], ax:The check
You forgot to initialize the CX register. The
repzdepends on it. Because your 'second method' had that erroneousdec cx, therepz cmpswinstruction may have seemed to work. However, the new corrected code will leave CX=0 and then the 'check' won't do any comparing at all! Simply addmov cx, 5*6*5. Also, you don't need to clear the direction flag again.Here also, these
movinstructions are adding the addresses of the arrays twice! Once through the initialization of SI / DI and a second time through the mention of A1 / A2 in the addressing mode.And of course better than subtracting 2 from the index registers, you should use the offset -2.
The result from calculating
AX = BX - DXgets lost by overwriting AX with the function number to exit the program!My suggestion that returns the difference in the DOS.Exitcode AL: