;********************
; Svar på oblig2
;
; author: Yngve Ådlandsvik
;
;********************
max_l EQU 20 ;Maksimal lengde på rekke
segment stack stack
resb 64
stacktop:
segment data
table:
dw 20,-10, 30, 30, 40, 10, 45,-10,-60, 20, 30
dw 45, 20,-10, 15, 25,-34,-15, 20,-10, 18, -4
result:
resw max_l
num_rows:
dw 0
num_cols:
dw 0
row_one:
dw 0
row_two:
dw 0
col_start:
dw 0
col_end:
dw 0
message_ant_rekker:
db 'Skriv inn tal rekker: $'
message_ant_kolonner:
db 'Skriv inn tal heiltal i kvar rekke: $'
message_rekker:
db 'Skriv inn nr. på rekkene: $'
message_kolonner:
db 'Skriv inn nr. på kolonnene: $'
message_resultat:
db 'Resultatet er: $'
message_crlf:
db 13, 10, '$'
print_number_buffer:
resb 5
db '$'
..start:
; initialiserer data- og stacksegmentregisterne
mov ax, stack
mov ss, ax
mov sp, stacktop
mov ax, data
mov ds, ax
; skriver ut melding og leser inn antall rekker
mov dx, message_ant_rekker
mov ah, 9
int 0x21
call read_number
mov [num_rows], ax
call print_lf
; skriver ut melding og leser inn antall kolonner
mov dx, message_ant_kolonner
mov ah, 9
int 0x21
call read_number
mov [num_cols], ax
call print_lf
main_loop:
; skriver ut melding og leser inn de to rekkenumrene
mov dx, message_rekker
mov ah, 9
int 0x21
call read_number
; om første nummer er null, exit
cmp ax, 0
je .exit
mov [row_one], ax
call read_number
mov [row_two], ax
call print_lf
; skriver ut melding og leser inn start- og sluttkolonne
mov dx, message_kolonner
mov ah, 9
int 0x21
call read_number
mov [col_start], ax
call read_number
mov [col_end], ax
call print_lf
; regner ut resultat-tabellen
call calc_result
; regner ut antall verdier som skal skrives ut (slutt - start + 1)
mov ax, [col_end]
sub ax, [col_start]
inc ax
; skriver ut resultatet
call print_result
jmp main_loop
; avslutter program, statuskode 0
.exit:
mov ax, 0x4c00
int 0x21
; Regner ut resultat-tabellen ved å sammenligne et subsett av to rader og
; å velge ut det høyeste nummeret
;
; input:
; ingenting
; output:
; ingenting
;
calc_result:
; tar vare på registre
pusha
mov cx, [col_start]
.loop:
; leser første nummer fra tabell
mov ax, cx
mov bx, [row_one]
call read_table
mov dx, ax
; leser andre nummer fra tabell
mov ax, cx
mov bx, [row_two]
call read_table
; sammenligner de to tallene, resultatet havner i ax
cmp ax, dx
jg .noswap
mov ax, dx
.noswap:
; regner ut hvor i resultat-tabellen vi skal plassere tallet
mov bx, cx
sub bx, [col_start]
; vi jobber med words, så dobler offsetet
sal bx, 1
; skriver tallet til resultat-tabellen
mov [result+bx], ax
; sjekker om vi er ferdig
inc cx
cmp cx, [col_end]
jbe .loop
; gjenoppretter registre, returnerer
popa
ret
; Leser et tall fra tabellen i minnet
;
; input:
; AX kolonnenummer, starter på 1
; BX rekkenummer, starter på 1
; output:
; AX tallet fra tabellen
;
read_table:
; tar vare på registre
push bx
push cx
push dx
; bytter om kolonne og rekke
xchg ax, bx
; gjør om til 0-baserte indexer
dec ax
dec bx
; ganger rekkenummer med antall kolonner for å finne start-indexen til rekken
mov cx, [num_cols]
mul cx
; legger sammen index og kolonnenummer for å finne tallets posisjon
add bx, ax
; vi jobber med words, så dobler offsetet
sal bx, 1
; leser tallet fra minne
mov ax, [table + bx]
; gjenoppretter registre, returnerer
pop dx
pop cx
pop bx
ret
; Leser et nummer fra stdin
; Takler bare positive nummer og ignorerer overflow
;
; input:
; ingenting
; output:
; AX nummer lest
; DL første tegn etter nummer
;
read_number:
; tar vare på registre
push bx
push cx
push dx
mov bx, 0
.loop:
; leser et tegn og sjekker om det er et siffer
mov ah, 1
int 0x21
cmp al, '0'
jb .done
cmp al, '9'
ja .done
; konverterer ascii-siffer til nummer
sub al, '0'
mov cl, al
; ganger oppsamlet nummer med 10, legger til det nye sifferet
mov ch, 0
mov ax, bx
mov bx, 10
mul bx
add ax, cx
mov bx, ax
jmp .loop
.done:
; gjenoppretter registre, plasserer returverdi i korrekt register
pop dx
mov dl, al
mov ax, bx
pop cx
pop bx
ret
; Skriver ut resultat-tabellen
;
; input:
; AX antall nummer i resultat-tabellen
; output:
; ingenting
;
print_result:
; tar vare på registre
pusha
mov dx, ax
; offset starter på null
mov cx, 0
.loop:
mov bx, cx
; vi jobber med words, så dobler offsetet
sal bx, 1
; leser nummeret fra minne
mov ax, [result + bx]
; skriver det ut
call print_number
; skriver ut et mellomrom mellom numrene
push dx
mov ah, 2
mov dl, 32
int 0x21
pop dx
; sjekker om vi er ferdig, hvis ikke looper vi
inc cx
cmp cx, dx
jne .loop
; skriver ut linjeskift på slutten
call print_lf
; gjenoppretter registre, returnerer
popa
ret
; Skriver ut et linjeskift
;
; input:
; ingenting
; output:
; ingenting
;
print_lf:
; tar vare på registre
push ax
push dx
; skriver ut linjeskift
mov ah, 2
mov dl, 10
int 0x21
; gjenoppretter registre, returnerer
pop dx
pop ax
ret
; Skriver et nummer til stdout
; Takler både positive og negative nummer, fjerner unødvendige nuller
;
; input:
; AX nummeret som skal skrives ut
; output:
; ingenting
;
print_number:
; tar vare på registre
push ax
push bx
push cx
push dx
cmp ax, 0
jge .notneg
; om nummeret er negativt skriver vi først ut et minustegn
mov bx, ax
mov dl, '-'
mov ah, 2
int 0x21
; så konverterer vi nummeret til et positivt
mov ax, bx
xor ax, 0xffff
inc ax
.notneg:
mov bx, 5
.loop:
; bruker rest etter divisjon til å lese et og et siffer
mov dx, 0
mov cx, 10
div cx
add dl, '0'
; lagrer sifrene i et midlertidig buffer
mov [print_number_buffer+bx-1], dl
; abryter loopen om det ikke er flere sifre å hente
cmp ax, 0
je .done
dec bx
jnz .loop
.done:
; skriver ut det konverterte nummeret
lea dx, [print_number_buffer+bx-1]
mov ah, 9
int 0x21
; gjenoppretter registre, returnerer
pop dx
pop cx
pop bx
pop ax
ret