我的汇编代码有问题。我想打印存储在寄存器cx中的数字,但是当我试图打印它时,它打印了ascii字符而不是ascii数字,所以我决定编写一个程序将ascii char转换为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
答案 0 :(得分:4)
这样的东西可以更好地打印十进制值(新代码是小写的):
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,它将在缓冲区[8]处添加“3”,在缓冲区[7]处添加“2”,在缓冲区[6]处添加“1” - 因此,如果您然后从缓冲区+ 6处打印字符串,则会得到“123” “。
我正在使用NASM语法,但希望它应该足够清楚。
答案 1 :(得分:1)
正如迈克尔在他的代码中写的那样,你需要清除DX,即在你分裂之前将其设为0。
但是如果你问我,你是否只需要以ASCII格式显示一个数字(当你想要显示一个数字时,不要笑脸)。在内部将值转换为ASCII可能非常不方便。
为什么不直接使用在程序开头定义的数组,该数组具有数字的所有ASCII值并选择对应的数组。
例如。 DB arr '0123456789'
并将每个数字与特定位置进行比较并打印出一个。自从我在8086编码以来已经很长时间了,但我记得将这个逻辑用于一个需要我打印十六进制数字的ASCII值的程序。所以我使用了一个0123456789ABCDEF
的数组,它运行得很好。
只是我的两分钱。因为你只想要结果。你计算它的方式并不重要。
答案 2 :(得分:0)
我想我应该发布一个更新。这篇文章真的帮助我找到了获取PHP CLI脚本的关键输入的方法。我无法在任何地方找到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的知识。
再次感谢大家!
答案 3 :(得分: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