assembly – 用DOS显示数字
我的任务是编写一个显示我的线性地址的程序
?程序的PSP.我写了以下内容: ORG 256 mov dx,Msg mov ah,09h ;DOS.WriteStringToStandardOutput int 21h mov ax,ds mov dx,16 mul dx ; -> Linear address is now in DX:AX ??? mov ax,4C00h ;DOS.TerminateWithExitCode int 21h ; ------------------------------ Msg: db 'PSP is at linear address $' 我搜索了DOS api(使用Ralph Brown’s interrupt list) 我想在DX中显示数字:AX为十进制数. 解决方法
DOS确实没有为我们提供直接输出数字的功能.
您必须先自己转换数字然后让DOS显示它 ?使用其中一个文本输出函数. 显示AX中保存的无符号16位数 在解决转换数字的问题时,有助于了解如何进行转换 (6 * 10000) + (5 * 1000) + (5 * 100) + (3 * 10) + (5 * 1) 方法1:通过降低10的幂来除法 处理从左到右的数字很方便,因为它 >通过将数字(65535)除以10000,我们获得一位数的商 mov bx,.List .a: xor dx,dx div word ptr [bx] ; -> AX=[0,9] is Quotient,Remainder DX xchg ax,dx add dl,"0" ;Turn into character [0,9] -> ["0","9"] push ax ;(1) mov ah,02h ;DOS.DisplayCharacter int 21h ; -> AL pop ax ;(1) AX is next dividend add bx,2 cmp bx,.List+10 jb .a ... .List: dw 10000,1000,100,10,1 虽然这种方法当然会产生正确的结果,但它有一些 >考虑较小的数字255及其分解: (0 * 10000) + (0 * 1000) + (2 * 100) + (5 * 10) + (5 * 1) 如果我们使用相同的5步过程,我们将获得“00255”.那两个领先 因此方法1是不切实际的,因此很少使用. 方法2:除以const 10 处理从右到左的数字似乎是违反直觉的 >通过将数字(65535)除以10,我们得到一个商(6553) 此时,堆栈保持我们的5个剩余部分,每个剩余部分是一个数字 mov bx,10 ;CONST xor cx,cx ;Reset counter .a: xor dx,dx ;Setup for division DX:AX / BX div bx ; -> AX is Quotient,Remainder DX=[0,9] push dx ;(1) Save remainder for now inc cx ;One more digit test ax,ax ;Is quotient zero? jnz .a ;No,use as next dividend .b: pop dx ;(1) add dl,"9"] mov ah,02h ;DOS.DisplayCharacter int 21h ; -> AL loop .b 第二种方法没有第一种方法的缺点: >因为当商变为零时我们停止,所以从来没有任何问题 显示DX:AX中保存的无符号32位数 在8086,需要级联2个分区来划分32位值 为了检查DX:AX中的dword是否为零,我在一个划痕中对两个OR进行了OR运算 我没有计算数字,需要注册,而是选择了sentinel 除此之外,此代码段与上面的方法2类似. mov bx,10 ;CONST push bx ;Sentinel .a: mov cx,ax ;Temporarily store LowDividend in CX mov ax,dx ;First divide the HighDividend xor dx,dx ;Setup for division DX:AX / BX div bx ; -> AX is HighQuotient,Remainder is re-used xchg ax,cx ;Temporarily move it to CX restoring LowDividend div bx ; -> AX is LowQuotient,9] push dx ;(1) Save remainder for now mov dx,cx ;Build true 32-bit quotient in DX:AX or cx,ax ;Is the true 32-bit quotient zero? jnz .a ;No,use as next dividend pop dx ;(1a) First pop (Is digit for sure) .b: add dl,02h ;DOS.DisplayCharacter int 21h ; -> AL pop dx ;(1b) All remaining pops cmp dx,bx ;Was it the sentinel? jb .b ;Not yet 显示DX:AX中保存的带符号32位数字 程序如下: 首先通过测试符号位找出带符号的数字是否为负数. 该片段的其余部分与无符号数字相同. test dx,dx ;Sign bit is bit 15 of high word jns .a ;It's a positive number neg dx ; neg ax ; | Negate DX:AX sbb dx,0 ;/ push ax dx ;(1) mov dl,"-" mov ah,02h ;DOS.DisplayCharacter int 21h ; -> AL pop dx ax ;(1) .a: mov bx,10 ;CONST push bx ;Sentinel .b: mov cx,9] push dx ;(2) Save remainder for now mov dx,ax ;Is the true 32-bit quotient zero? jnz .b ;No,use as next dividend pop dx ;(2a) First pop (Is digit for sure) .c: add dl,02h ;DOS.DisplayCharacter int 21h ; -> AL pop dx ;(2b) All remaining pops cmp dx,bx ;Was it the sentinel? jb .c ;Not yet 我是否需要针对不同数量大小的单独例程? 在需要偶尔显示AL,AX或DX:AX的程序中,您可以 ; IN (al) OUT () DisplaySignedNumber8: push ax cbw ;Promote AL to AX call DisplaySignedNumber16 pop ax ret ; ------------------------- ; IN (ax) OUT () DisplaySignedNumber16: push dx cwd ;Promote AX to DX:AX call DisplaySignedNumber32 pop dx ret ; ------------------------- ; IN (dx:ax) OUT () DisplaySignedNumber32: push ax bx cx dx ... 或者,如果您不介意使用AX和DX寄存器 ; IN (al) OUT () MOD (ax,dx) DisplaySignedNumber8: cbw ; --- --- --- --- - ; IN (ax) OUT () MOD (ax,dx) DisplaySignedNumber16: cwd ; --- --- --- --- - ; IN (dx:ax) OUT () MOD (ax,dx) DisplaySignedNumber32: push bx cx ... (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- windows-server-2008-r2 – 我应该将Windows Server 2008 R
- windows-8 – Windows 8 JavaScript应用程序开发 – 共享魅
- windows-server-2008 – Windows Update代理更新失败
- windows-7 – 我可以修改Windows 7环境以允许.NET程序始终以
- .net – 我们可以将’Microsoft.ACE.Oledb.12.0.dll’的引用
- windows-server-2008 – Windows 2008 RAID失败的Redudancy
- kms – windows server 2012 r2 – 激活宽限期?
- 从弹出菜单win32 api Python中选择项目
- 在Windows控制台中设置Mercurial以完成命令
- windows-7 – 从Windows XP客户端IRPStackSize和访问Window