Assemblaggio, stampa del numero di ascii

Ho un problema con il mio codice assembly. Voglio stampare il numero memorizzato nel registro cx, ma quando ho provato a stamparlo, ha stampato caratteri ascii invece del numero ASCII, così ho deciso di scrivere una procedura per convertire il carattere ASCII in ASCII. Il problema è che quando provo a chiamare quella procedura, il programma si blocca e devo riavviare dosbox. Qualcuno sa che cosa non va con questo codice? Grazie.

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 

Qualcosa di simile funzionerebbe meglio per la stampa di un valore decimale (il nuovo codice è in minuscolo):

  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 

Invece di stampare direttamente ogni carattere, aggiunge i caratteri a un buffer in ordine inverso. Per il valore 123 aggiungerebbe “3” al buffer [8], “2” al buffer [7] e “1” al buffer [6] – quindi se si stampa la stringa iniziando dal buffer + 6 si ottiene “123 “.
Sto usando la syntax NASM, ma si spera che dovrebbe essere abbastanza chiaro.

Come Michael ha scritto nel suo codice, è necessario cancellare DX, cioè renderlo 0 prima di dividerlo.

Ma se me lo chiedi, se hai solo bisogno di visualizzare un numero nel modulo ASCII (non ottenere una faccina quando vuoi che venga visualizzato un numero). Convertire il valore in ASCII internamente può essere abbastanza scomodo.

Perché non usi semplicemente un array definito all’inizio del programma che ha tutti i valori ASCII dei numeri e scegli quello a cui corrisponde.

per es. DB arr '0123456789' e confronta ciascun numero con la posizione specifica e stampa quello. È passato molto tempo da quando ho codificato in 8086, ma ricordo di aver usato questa logica per un programma che mi richiedeva di stampare un valore ASCII di un numero esadecimale. Quindi ho usato un array che aveva 0123456789ABCDEF e ha funzionato perfettamente.

Solo i miei due centesimi. Dal momento che volevi solo il risultato. non importa come lo si calcola.

Ho pensato di pubblicare un aggiornamento a questo. Questo post mi ha davvero aiutato a cercare un modo per ottenere input chiave per gli script CLI PHP. Non sono riuscito a trovare una soluzione Windows / DOS da nessuna parte, quindi ho optato per un programma esterno.

Sto usando una versione molto vecchia dell’assembler di a86, quindi il codice è piuttosto semplice.

(e come distriggersre “Esegui snippet di codice”?)

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

Ecco il codice ben collaudato per il numero di stampa

 .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