instruction instrucciones assembly x86 ascii x86-16

assembly - instruction - instrucciones x86



Asamblea, impresión del número de ASCII (4)

Algo así funcionaría mejor para imprimir un valor decimal (el nuevo código está en minúscula):

mov byte [buffer+9],''$'' lea si,[buffer+9] MOV AX,CX ;CX = VALUE THAT I WANT TO CONVERT MOV BX,10 ASC2: mov dx,0 ; clear dx prior to dividing dx:ax by bx DIV BX ;DIV AX/10 ADD DX,48 ;ADD 48 TO REMAINDER TO GET ASCII CHARACTER OF NUMBER dec si ; store characters in reverse order mov [si],dl CMP AX,0 JZ EXTT ;IF AX=0, END OF THE PROCEDURE JMP ASC2 ;ELSE REPEAT EXTT: mov ah,9 ; print string mov dx,si int 21h RET buffer: resb 10

En lugar de imprimir cada carácter directamente, agrega los caracteres a un búfer en orden inverso. Para el valor 123 agregaría ''3'' en el búfer [8], ''2'' en el búfer [7] y ''1'' en el búfer [6] - por lo que si imprime la cadena que comienza en el búfer + 6 obtendrá "123 ".
Estoy usando la sintaxis de NASM, pero espero que sea lo suficientemente clara.

Tengo un problema con mi código de ensamblaje. Quiero imprimir el número almacenado en el registro cx, pero cuando traté de imprimirlo, imprimí el carácter ascii en lugar del número ascii, así que decidí escribir un procedimiento para convertir ascii char en valor ascii. El problema es que cuando intento llamar a ese procedimiento, el programa se congela y tengo que reiniciar dosbox. ¿Alguien sabe qué está mal con este código? Gracias.

P4 PROC MOV AX,CX ;CX = VALUE THAT I WANT TO CONVERT MOV BX,10 ASC2: DIV BX ;DIV AX/10 ADD DX,48 ;ADD 48 TO REMAINDER TO GET ASCII CHARACTER OF NUMBER PUSH AX ;SAVE AX MOV AH,2 ;PRINT REMAINDER STORED IN DX INT 21H ;INTERRUP POP AX ;POP AX BACK CMP AX,0 JZ EXTT ;IF AX=0, END OF THE PROCEDURE JMP ASC2 ;ELSE REPEAT EXTT: RET P4 ENDP


Como Michael ha escrito en su código, debe borrar DX, es decir, hacerlo 0 antes de dividir.

Pero si me preguntas, si solo necesitas mostrar un número en el formulario ASCII (no obtener una carita sonriente cuando quieres que se muestre un número). Convertir el valor a ASCII internamente puede ser bastante inconveniente.

¿Por qué no utiliza una matriz definida al comienzo del programa que tiene todos los valores ASCII de los números y elige la que corresponde?

por ej. DB arr ''0123456789'' y compare cada número con la posición particular e imprima esa. Ha pasado mucho tiempo desde que codifiqué en 8086, pero recuerdo que utilicé esta lógica para un programa que requería que imprimiera un valor ASCII de un número hexadecimal. Así que utilicé una matriz que tenía 0123456789ABCDEF y funcionó perfectamente.

Solo mis dos centavos. Como solo querías el resultado. realmente no importa cómo lo calcule.


Pensé que debería publicar una actualización de esto. Esta publicación realmente me ayudó a buscar una forma de obtener información clave para los scripts CLI de PHP. No pude encontrar una solución Windows / DOS en ninguna parte, así que opté por un programa externo.

Estoy usando una versión realmente antigua del ensamblador a86, por lo que el código es bastante básico.

(¿y cómo desactivo "Ejecutar fragmento de código"?)

;Key input for scripts that can use some "shell" function. ;Waits for a keypress then returns a string "key:scan" ;if "key" is 0 then you can check "scan" for arrow keys ;or other non-ASCII keys this way. mov ah,0 int 16h push ax mov ah,0 mov cx,ax call ASC mov dx,'':'' call COUT pop ax shr ax,8 mov ah,0 mov cx,ax call ASC jp EXIT COUT: mov ah,2 int 21h ret STROUT: mov ah,9 mov dx,si int 21h ret ASC: mov byte [buffer+9],''$'' lea si,[buffer+9] mov ax,cx mov bx,10 ASC_LOOP: mov dx,0 div bx add dx,48 dec si mov [si],dl cmp ax,0 jz STROUT jmp ASC_LOOP EXIT: mov ah,4ch int 21h ret buffer: db " " ; 10 spaces. no "resb" in my assembler.

Un script PHP de muestra para probarlo en:

<?php function getKey() { return shell_exec("getkey.com"); } print "Press [ESC] to exit./n/n"; $key = ""; while (ord($key) != 27) { $getch = explode(":",getKey()); $key = chr($getch[0]); $scan = $getch[1]; if (ord($key) != 0) { print $key; } else { print "SCAN:$scan/n"; } } ?>

Es cierto que después de todo lo dicho y hecho me di cuenta de que podría haber hecho lo mismo en C ++. Pero aprendí mucho más sobre ASM esta vez.

Así que gracias de nuevo amigos!


Aquí está el código bien probado para imprimir el número

.186 .model SMALL .STACK 100h .data HelloMessage db ''Hello World'', 13, 10, ''$'' SuperNumber dw 13565 .code ; Writes word number from AX to output ; Usage ; .186 ; .... ; mov ax, 13444 ; call PRINT_NUMBER PRINT_NUMBER PROC NEAR ; Outputs integer word number stored in AX registry. Requires CPU ; Save state of registers. PUSHA ; Save all general purpose registers PUSH BP ; We''re going to change that. ; we need variables ; word number; 2 bytes ; byte digitsCount; 1 byte ; reserving space for variables on stack (3 bytes) mov bp, sp; ; bp := address of the top of a stack sub sp, 3*8 ; allocate 3 bytes on stack. Addresses of variables will be ; number: WORD PTR [rbp - 2*8] ; digitsCount: BYTE PTR [rbp - 3*8] ; Getting digits ; number = ax; ; digitsCount = 0; ; do ; { ; push number%10; ; digitsCount++; ; number = number / 10; ; } ; while (number > 0) mov WORD PTR [bp - 2*8], ax ; number = ax; mov BYTE PTR [bp - 3*8], 0 ; digitsCount = 0; getDigits: ; do mov ax, WORD PTR [bp - 2*8]; number/10: ax = number / 10, dx: number % 10 ;cwd mov dx, 0 mov bx, 10 div bx push dx ; push number%10 mov WORD PTR[bp - 2*8], ax; number = number/10; inc byte PTR[bp - 3*8] ; digitsCount++; cmp WORD PTR[bp - 2*8], 0; compare number and 0 je getDigitsEnd ; if number == 0 goto getDigitsEnd jmp getDigits ; goto getDigits; getDigitsEnd: mov ah, 9 mov dx, offset HelloMessage int 21h ;while (digitsCount > 0) ;{ ; pop digit into ax ; print digit ; digitsCount--; ;} printDigits: cmp BYTE PTR[bp - 3*8], 0; compare digits count and 0 je printDigitsEnd ; if digitsCount == 0 goto printDigitsEnd pop ax ; pop digit into al add al, 30h ; get character from digit into al mov ah, 0eh ; wanna print digit! int 10h ; BIOS, do it! dec BYTE PTR[bp - 3*8] ; digitsCount-- jmp printDigits ; goto printDigits printDigitsEnd: ; Deallocate local variables back. mov sp, bp ; Restore state of registers in reverse order. POP BP POPA ; Exit from procedure. RET PRINT_NUMBER ENDP start: mov ax, @data mov ds, ax mov ah, 9 mov dx, offset HelloMessage int 21h mov ax, 64454 call Print_Number mov ah, 4ch int 21h end start