Addition and Subtraction + Flags (status register) [INTEL 8086]
🌐 This is an automatic translation of a topic from Underc0de, the largest Spanish-speaking hacking and IT community. Read the original (Spanish) and reply →
Olger346 ·
The goal of this program is to observe how the flags change after executing an arithmetic operation, in this case addition and subtraction.<br />I hope I documented the code well enough so that everything is clear. I also want to mention that I took the scanum routine from a wizard's site, but you can see what it does by emulating it step by step.<br /><br />The variables are stored in the cx register, which has to be moved into a variable, otherwise the variable's value is lost.<br />The program only works in a range from -128 to 127. <br />Some flags will probably not change.<br /><br />I hope it's useful. ^w^bCódigo: asm
<br />imprime_car macro car<br /> <br /> mov ah,10<br /> mov al,car<br /> mov bh,0<br /> mov cx,1<br /> int 10h <br /><br />endm<br /><br />print macro cad<br /> mov ah,9<br /> lea dx,cad<br /> int 21h<br /> <br />endm <br /><br />getch macro dato<br /> <br /> mov ah,0 ; servicio 0 de Teclado<br /> int 16h ; Interrupcion de teclado<br /> <br /> mov dato,al<br /> <br />endm <br /><br />cursor_xy macro X,Y<br /> <br /> mov ah,2 ; servicio 2 de video<br /> mov dh,Y ; coordenada de la fila<br /> mov dl,X ; coordenada de la columna<br /> mov bh,0 <br /> int 10h ; interrupcion de video<br /> <br />endm<br /><br />putc macro car<br /> <br /> mov ah,10<br /> mov al,car<br /> mov bh,0<br /> mov cx,1<br /> int 10h<br />endm <br /><br />getint macro dato ;modificaciones de la macro getch<br /> <br /> mov ah,0 ; servicio 0 de Teclado<br /> int 16h ; Interrupcion de teclado<br /> <br /> mov dato,ax ;cambiar a ax para recojer datos de 2bytes osea mayores a 127<br /> <br />endm <br /><br />.data<br /> error db "error",13,10,36<br /> h1 db " ",13,10,<br /> db " Registro de Estado Olger346",13,10,<br /> db " Operaciones con Negativos ",13,10,<br /> db " + Suma 11R122",13,10,<br /> db " - Resta ",13,10,<br /> db " ESC ",13,10,36<br /> <br /> h2 db " Valor de A (127-128) ",13,10,36 <br /> h3 db " Valor de B (127-128) ",13,10,36<br /> <br /> h4 db " - - - - O D I T S Z - A - P - C ",13,10,<br /> db " ",13,10,<br /> db " ",13,10, <br /> db " Aritmeticos & Logicos Control ",13,10,<br /> db " Acarreo = Direccion = ",13,10,<br /> db " Paridad = Interrupcion = Valor ",13,10,<br /> db " Auxiliar = Trazado = A= ",13,10,<br /> db " Cero = B= ",13,10,<br /> db " Signo = resultado ",13,10,<br /> db " Desbordamiento = ",13,10,36<br /> <br /> B db " ",36 ;variable xa impresion hexadecimal y otras<br /> A dw ? ;1er valor a introducir<br /> C dw ? ;segundo valor a introducir<br /> G db ? <br /> M dw ? ;resultado de suma o resta<br /> I dw ? ;recoje un caracter ya sea +-<br /> X db 40 ;variable de barrido de impresion <br /> make_minus db ?<br /> ten dw 10<br /> msg db 0,25,36 <br /> K db 16<br /> bla db " ",36 <br /> ;variables de control de ciclo<br /> U db 40<br /> V db 40<br /> W db 37<br />flag dw ? ;variable para almacenar el registro de estado<br /> ntr db "0",36 <br /> control db 40 <br /> ecchi db 40<br /><br /> <br />.stack<br /> <br />.code<br /> <br /> mov ax,@data<br /> mov ds,ax <br /> <br /> cursor_xy 0,1 <br /> print h1 <br /> cursor_xy 26,6 ;coloca cursor en el primer ingreso del signo aritmetico<br /> <br /> <br />ciclo: <br /> <br /> mov I,0<br /> cursor_xy 26,6 <br /> print bla<br /> cursor_xy 26,6 <br /> getint I <br /> mov ax,I<br /> mov B,al ;se imprime <br /> print B <br /> <br /> cmp I,4E2Bh ;podeis cambiar esto a 1 y funcionara con el 1 del teclado<br /> je suma<br /> <br /> cmp I, 4A2Dh ;igual podeis cambiar a 2<br /> je resta <br /> <br /> cmp I,01<br /> je final<br /> <br /> print error<br /> jmp ciclo <br /> <br /> ;call SCAN_NUM ;scanea el signo aritmetico <br /> ;mov G,cx <br /> <br /> <br />suma:<br /> <br /> mov cx,0 ; en cx queda un valor hay que resetearlo para que no haya basura en el valor que se vuelve a introducir nuevamente<br /> mov A,0 ;limpiamos el valor que tenia la variable A<br /> cursor_xy 0,7 <br /> print h2<br /> cursor_xy 38,7 ;coloca cursor en el primer ingreso del primer valor<br /> call SCAN_NUM ;scanea el primer valor<br /> mov A,cx <br /> <br /> cmp A,128<br /> je suma<br /> <br /> cmp A,-129<br /> je suma<br /> <br /> mov cx,0<br /> mov C,0<br /> cursor_xy 0,8<br /> print h3<br /> cursor_xy 38,8 ;coloca cursor en el primer ingreso del segund valor<br /> call SCAN_NUM ;scanea el segundo valor<br /> mov C,cx <br /> <br /> cmp C,128<br /> je suma<br /> <br /> cmp C,-128<br /> je suma<br /> <br /> mov ax,A ; mov para sumar<br /> add ax,C ; anade a ax lo q tiene c<br /> mov M,ax ; mov la suma a la variable M<br /> <br /> mov ax,M<br /> xchg al,ah<br /> push ax<br /> call HEXA<br /> <br /> cursor_xy 60,22 <br /> print B ;imprime la parte high de ax osea M<br /> <br /> mov ax,M<br /> push ax<br /> call HEXA<br /> <br /> <br /> cursor_xy 62,22<br /> print B ;imprime 1byte de la parte low de ax osea M<br /> <br /> cursor_xy 0,14<br /> print h4 ;imprime esquema de flag<br /> <br /> <br /> mov ax,A ; mov para sumar<br /> add ax,C ; anade a ax lo q tiene c<br /> <br /> pushf ; ax=Flag<br /> pop ax ;pop F para almacenar las flags <br /> <br /> cursor_xy 0,16 ;impresion de flags<br /> mov flag,ax<br /> <br /> jmp binario4<br /> <br /> <br /> <br /> <br />resta: <br /> <br /> mov cx,0 ; en cx queda un valor hay que resetearlo para que no haya basura en el valor que se vuelve a introducir nuevamente<br /> mov A,0 ; limpiamos el valor que habia en A<br /> cursor_xy 0,7 <br /> print h2<br /> cursor_xy 38,7 ;coloca cursor en el primer ingreso del primer valor<br /> call SCAN_NUM ;scanea el primer valor<br /> mov A,cx <br /> <br /> cmp A,128<br /> je resta<br /> <br /> cmp A,-129<br /> je resta<br /> <br /> mov cx,0 ; en cx queda un valor hay que resetearlo para que no haya basura en el valor que se vuelve a introducir nuevamente<br /> mov C,0 ;limpiamos el valor que queda en C<br /> cursor_xy 0,8<br /> print h3<br /> cursor_xy 38,8 ;coloca cursor en el primer ingreso del segund valor<br /> call SCAN_NUM ;scanea el segundo valor<br /> mov C,cx<br /> <br /> cmp C,128<br /> je resta<br /> <br /> cmp C,-129<br /> je resta <br /> <br /> <br /> mov ax,A ; mov para sumar<br /> sub ax,C ; anade a ax lo q tiene c<br /> mov M,ax ; mov la suma a la variable M<br /> <br /> mov ax,M<br /> xchg al,ah<br /> push ax<br /> call HEXA<br /> cursor_xy 60,22<br /> print B ;imprime la parte high de ax osea M<br /> <br /> mov ax,M<br /> push ax<br /> call HEXA<br /> cursor_xy 62,22<br /> print B ;imprime 1byte de la parte low de ax osea M<br /> <br /> <br /> <br /> cursor_xy 0,14<br /> print h4 ;imprime esquema de flag <br /> <br /> mov ax,A ; mov para sumar<br /> sub ax,C ; anade a ax lo q tiene c<br /> <br /> pushf ; ax=Flag<br /> pop ax ;pop F para almacenar las flags <br /> <br /> cursor_xy 0,16 ;impresion de flags<br /> mov flag,ax<br /> <br /> jmp binario4<br /> <br /> <br /><br />binario1:<br /> <br /> mov ax,A <br /> ;mov bx,ax<br /> and ax,1 ;cambias esto ; Residuo de dividir entre 2 <br /> <br /> <br /> cursor_xy U,9 <br /> add al,48 ;suma para que aparezca el caracter en pantalla ascii <br /> putc al<br /> <br /> sub U,2 ; y esto para convertir a octal y ya<br /> shr A,1 <br /> dec K ;sub K,1 <br /> <br /> cmp U,28 ;barrido para impresion de pantalla<br /> jae binario1<br /> add U,14<br /> <br /> jmp binario2<br /> <br />binario2:<br /><br /> mov ax,C <br /> ;mov bx,ax<br /> and ax,1 ;cambias esto ; Residuo de dividir entre 2 <br /> <br /> <br /> cursor_xy V,10 <br /> add al,48 ;suma para que aparezca el caracter en pantalla ascii <br /> putc al<br /> <br /> sub V,2 ; y esto para convertir a octal y ya<br /> shr C,1 <br /> dec K ;sub K,1 <br /> <br /> cmp V,28 ;barrido para impresion de pantalla<br /> jae binario2<br /> add V,14<br /> jmp binario3 <br /> <br />binario3:<br /> <br /> <br /> mov ax,M <br /> ;mov bx,ax<br /> and ax,1 ;cambias esto ; Residuo de dividir entre 2 <br /> <br /> <br /> cursor_xy X,11<br /> add al,48 ;suma para que aparezca el caracter en pantalla ascii <br /> putc al<br /> <br /> sub X,2 ; y esto para convertir a octal y ya<br /> shr M,1 <br /> dec K ;sub K,1 <br /> <br /> cmp X,28 ;barrido para impresion de pantalla<br /> jae binario3<br /> add X,14 <br /> jmp ciclo<br /><br />binario4:<br /> <br /> <br /> mov ax,flag <br /> ;mov bx,ax<br /> and ax,1 ;cambias esto ; Residuo de dividir entre 2 <br /> <br /> <br /> cursor_xy W,16<br /> add al,48 ;suma para que aparezca el caracter en pantalla ascii <br /> putc al<br /> <br /> sub W,2 ; y esto para convertir a octal y ya<br /> sub control,2<br /> shr flag,1 <br /> ;sub K,1 <br /> <br /> cmp ecchi,40<br /> je acarreo<br /> cmp control,34 <br /> je par <br /> cmp control,30<br /> je aux<br /> cmp control,26<br /> je zero<br /> cmp control,24<br /> je sig<br /> cmp control,20<br /> je inter <br /> <br /> <br /> <br /> cmp W,18 ;barrido para impresion de pantalla<br /> jae binario4<br /> add W,20<br /> add control,20<br /> jmp binario1 <br /> <br /> <br />par:<br /> cursor_xy 20,19<br /> putc al<br /> jmp binario4 <br /><br />zero:<br /> cursor_xy 20,21<br /> putc al<br /> jmp binario4<br />sig:<br /> cursor_xy 20,22<br /> putc al<br /> cursor_xy 20,23<br /> print ntr<br /> jmp binario4<br />inter: <br /> cursor_xy 40,19<br /> putc al <br /> cursor_xy 40,18<br /> print ntr<br /> cursor_xy 40,20<br /> print ntr<br /> jmp binario4<br /><br />acarreo: <br /> <br /> cursor_xy 20,18<br /> putc al<br /> sub ecchi,2<br /> jmp binario4<br />aux:<br /> cursor_xy 20,20<br /> putc al<br /> jmp binario4 <br /> <br /> <br />final:<br /> mov ah,21h<br /> int 21h<br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br /> <br />;/////////RUTINA SCAN_NUM<br /> <br />; -32768 : 65535<br />; gets the multi-digit SIGNED number from the keyboard,<br />; and stores the result in CX register:<br />SCAN_NUM PROC NEAR<br /> PUSH DX<br /> PUSH AX<br /> PUSH SI<br /> <br /> MOV CX, 0<br /><br /> ; reset flag:<br /> MOV make_minus, 0<br /><br />next_digit:<br /><br /> ; get char from keyboard<br /> ; into AL:<br /> MOV AH, 00h<br /> INT 16h<br /> ; and print it:<br /> MOV AH, 0Eh<br /> INT 10h<br /><br /> ; check for MINUS:<br /> CMP AL, '-'<br /> JE set_minus<br /><br /> ; check for ENTER key:<br /> CMP AL, 0Dh ; carriage return?<br /> JNE not_cr<br /> JMP stop_input<br />not_cr:<br /><br /><br /> CMP AL, 8 ; 'BACKSPACE' pressed?<br /> JNE backspace_checked<br /> MOV DX, 0 ; remove last digit by<br /> MOV AX, CX ; division:<br /> DIV ten ; AX = DX:AX / 10 (DX-rem).<br /> MOV CX, AX<br /> PUTC ' ' ; clear position.<br /> PUTC 8 ; backspace again.<br /> JMP next_digit<br />backspace_checked:<br /><br /><br /> ; allow only digits:<br /> CMP AL, '0'<br /> JAE ok_AE_0<br /> JMP remove_not_digit<br />ok_AE_0: <br /> CMP AL, '9'<br /> JBE ok_digit<br />remove_not_digit: <br /> PUTC 8 ; backspace.<br /> PUTC ' ' ; clear last entered not digit.<br /> PUTC 8 ; backspace again. <br /> JMP next_digit ; wait for next input. <br />ok_digit:<br /><br /><br /> ; multiply CX by 10 (first time the result is zero)<br /> PUSH AX<br /> MOV AX, CX<br /> MUL ten ; DX:AX = AX*10<br /> MOV CX, AX<br /> POP AX<br /><br /> ; check if the number is too big<br /> ; (result should be 16 bits)<br /> CMP DX, 0<br /> JNE too_big<br /><br /> ; convert from ASCII code:<br /> SUB AL, 30h<br /><br /> ; add AL to CX:<br /> MOV AH, 0<br /> MOV DX, CX ; backup, in case the result will be too big.<br /> ADD CX, AX<br /> JC too_big2 ; jump if the number is too big.<br /><br /> JMP next_digit<br /><br />set_minus:<br /> MOV make_minus, 1<br /> JMP next_digit<br /><br />too_big2:<br /> MOV CX, DX ; restore the backuped value before add.<br /> MOV DX, 0 ; DX was zero before backup!<br />too_big:<br /> MOV AX, CX<br /> DIV ten ; reverse last DX:AX = AX*10, make AX = DX:AX / 10<br /> MOV CX, AX<br /> PUTC 8 ; backspace.<br /> PUTC ' ' ; clear last entered digit.<br /> PUTC 8 ; backspace again. <br /> JMP next_digit ; wait for Enter/Backspace.<br /> <br /> <br />stop_input:<br /> ; check flag:<br /> CMP make_minus, 0<br /> JE not_minus<br /> NEG CX<br />not_minus:<br /><br /> POP SI<br /> POP AX<br /> POP DX<br /> RET<br /><br />SCAN_NUM ENDP <br /><br />;//////// RUTINA HEXADECIMAL<br /> <br />Hexa proc near<br /> push bp<br /> mov bp,sp<br /> mov al,[bp+4]<br /> shr al,4<br /> add al,48<br /> cmp al,58<br /> js nible2<br /> add al,7<br />nible2: mov B,al<br /> mov al,[bp+4]<br /> shl al,4<br /> shr al,4<br /> add al,48<br /> cmp al,58<br /> js nible1<br /> add al,7<br />nible1: mov B[1],al<br /> pop bp<br /> ret<br />Hexa endp <br /><br />;////////////FIN DEL PROGRAMA<br /><br /><br /><br />.exit<br />
rfgaz ·
Very good, even though I understand very little of it, that's what makes me enjoy looking at the code.<br /><br />