'Accurate LINE FEED in assembly language
I am writing an asm program, which has to print the contents of 2D array. I succeeded in adding spaces to elements of an array, but I can't add line feeds when the row is over. I tried to add some labels, e.g. @line which adds line feeds and carriage returns, but when i add return statement the loop goes infinitely. What should I do?
Here is my code:
.model small
.stack 100h
.data
message db 0ah,0dh,'Initial array: $',0ah,0dh
array dw 1, 2, 3, 4, 5, 6
dw 7, 8, 9, 10, 11, 12
dw 13, 14, 15, 16, 17, 18
dw 19, 20, 21, 22, 23, 24
CR_LF db 0dh,0ah, '$'
x dw ?
buff dw ?
.code
main:
mov ax,@data
mov ds,ax
xor ax,ax
printmessage:
mov ah, 09h
lea dx, message
int 21h
mov cx, 24
mov si, 0
@sec_row:
mov ax, array[si]
cmp buff, 24
je @end
jl @main
@main:
mov x, ax
push ax
cmp ax, 0
jns @num_count
mov ah, 02h
mov dl, '-'
int 21h
pop ax
neg ax
@num_count:
xor cx, cx
mov bx, 10
@dvsn:
xor dx, dx
div bx
push dx
inc cx
test ax, ax
jnz @dvsn
mov ah, 02h
@output:
pop dx
add dl, 30h
int 21h
loop @output
mov dl, ' '
mov ah, 2
int 21h
inc buff
add si, 2
jmp @sec_row
loop @sec_row
@end:
mov ax,4c00h
int 21h
end main
Solution 1:[1]
It will be easier to make the requested addition to the program once the code has been cleaned and works correctly.
Correct the unbalanced stack error
push ax <<< cmp ax, 0 jns @num_count mov ah, 02h mov dl, '-' int 21h pop ax <<< neg ax @num_count:
When the number from the array turns out to be negative, you display a minus character, and because you know that this will clobber the AX register, you preserve AX on the stack. Good idea, wrong execution! Currently your code does push ax for any of the numbers while it does pop ax only for the negative numbers. Seeing that your array of numbers exclusively has positive numbers, it is to be expected that the stack will fill up. That will at some point cause problems.
cmp ax, 0
jge @num_count
push ax ; (1)
mov ah, 02h
mov dl, '-'
int 21h
pop ax ; (1)
neg ax
@num_count:
Remove the leftovers from previous drafts
mov cx, 24 <<< 1 mov si, 0 @sec_row: ... jl @main <<< 2 @main: <<< 2 mov x, ax <<< 3 ... add si, 2 jmp @sec_row loop @sec_row <<< 1
(1) At some time you planned on using the loop instruction for this task but later you changed your mind, perhaps because you saw that you needed CX for the number conversion? You should have removed these lines.
(2) At some time these jl @main and @main would have been not adjacent and making good sense, but here they don't make sense anymore!
(3) At some time this mov x, ax would have preserved the AX register as required for the display of the minus character, but later you changed your mind and started using the stack. You should have removed this line.
Write the loop clearer
Your loop is using the memory-based buff variable to control the number of iterations (24). At the same time your loop is using a register-based variable (SI) that contains the current offset in the array. You don't need both together. Once the SI register gets the value 48 (24 x 2), the end of the array has been reached. Use that info to control the loop:
xor si, si ; Offset in the array
@sec_row:
mov ax, array[si] ; Load current element
cmp ax, 0 \
jge @num_count |
... | <PRINTNUMBER>
mov dl, ' ' |
int 21h /
add si, 2 ; Elements are word-sized
cmp si, 24 * 2 ; Process 24 elements
jb @sec_row
Moving on to displaying the rows of the matrix on separate rows of the screen.
Method 1 introduces a special down-counter that can inform us that the end of the current row has been reached. Since there are 6 elements in a row, this down-counter will be initialized at 6 and once it runs out we display the newline sequence and (very important) we re-initialize the down-counter.
mov di, 6 ; DownCount = Number of columns
xor si, si ; Offset in the array
...
<PRINTNUMBER>
dec di
jnz @not_yet
lea dx, CR_LF
mov ah, 09h
int 21h
mov di, 6
@not_yet:
Method 2 uses what we call nested loops. Your matrix has 2 dimensions, why not give the loop 2 dimensions? The outer loop runs the vertical direction that has 4 rows, and the inner loop runs the horizontal direction that has 6 columns. Each time the inner loop finishes we display the newline. At the conclusion of the outer loop we will have processed 4 times 6 elements plus their accompanying newline.
xor si, si ; Offset in the array
mov di, 4 ; OuterLoopCount = Number of rows
@OuterLoop:
mov bp, 6 ; InnerLoopCount = Number of columns
@InnerLoop:
mov ax, array[si] ; Load current element
<PRINTNUMBER>
dec bp
jnz @InnerLoop
lea dx, CR_LF
mov ah, 09h
int 21h
dec di
jnz @OuterLoop
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Sep Roland |
