2

アセンブリコードに問題があります。レジスタcxに格納されている数値を出力したいのですが、印刷しようとすると、ASCII番号ではなくASCII文字が出力されるため、ASCII文字をASCII値に変換するプロシージャを作成することにしました。問題は、そのプロシージャを呼び出そうとすると、プログラムがフリーズし、dosboxを再起動する必要があることです。誰かがこのコードの何が問題なのか知っていますか?ありがとう。

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
4

4 に答える 4

4

このようなものは、10進値を印刷するのに適しています(新しいコードは小文字です)。

        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

各文字を直接印刷する代わりに、逆の順序で文字をバッファに追加します。値123の場合、buffer [8]に「3」、buffer [7]に「2」、buffer [6]に「1」が追加されます。したがって、buffer + 6で始まる文字列を出力すると、「123」になります。 "。
私はNASM構文を使用していますが、うまくいけば十分に明確であるはずです。

于 2013-03-25T18:02:31.803 に答える
1

Michaelが彼のコードで書いたように、DXをクリアする必要があります。つまり、分割する前に0にします。

しかし、私に尋ねると、ASCII形式で数字を表示するだけでよい場合(数字を表示したいときにスマイリーフェイスを取得しないでください)。値を内部でASCIIに変換すると、非常に不便になる可能性があります。

プログラムの先頭で定義された、数値のすべてのASCII値を持つ配列を使用して、対応するものを選択してみませんか。

たとえば。DB arr '0123456789' 各番号を特定の位置と比較して、その番号を印刷します。8086でコーディングしてからかなりの時間が経ちましたが、このロジックをプログラムに使用したことを覚えています。このロジックでは、16進数のASCII値を出力する必要がありました。だから私は持っていたアレイを使用しました0123456789ABCDEF、そしてそれは完全に機能しました。

ちょうど私の2セント。結果だけが欲しかったので。どのように計算するかは重要ではありません。

于 2013-04-01T18:01:17.483 に答える
0

私はこれに更新を投稿する必要があると思いました。この投稿は、PHPCLIスクリプトのキー入力を取得する方法を探すのに本当に役立ちました。Windows / DOSソリューションがどこにも見つからなかったので、外部プログラムを選択しました。

私は本当に古いバージョンのa86アセンブラーを使用しているので、コードはかなり基本的です。

(「コードスニペットの実行」をオフにするにはどうすればよいですか?)

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

それをテストするためのサンプルPHPスクリプト:

<?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";
	}
}

?>

確かに、結局のところ、私はC++でも同じことができることに気づきました。しかし、今回はASMについてもっと多くのことを学びました。

皆さん、ありがとうございました!

于 2014-11-17T03:06:31.933 に答える
0

これは、番号を印刷するための十分にテストされたコードです

.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
于 2015-03-06T18:21:16.220 に答える