;******************** ; 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