2012-09-21 41 views
3

我試圖序列中只打印的數字即轉換十六進制/十進制數(Assemly-TASM)

1,2,3,4,5,6,7,8,9,10,11 ,12,13,14,15,16,17,18,19,20

使用循環, 首先我將每個數字轉換成Hexa打印它重置爲十進制增量1,然後打印下一個,直到數字等於9, 當數字等於9時,我使用DAA簡單地輸入數字,在旋轉和移位數字後,我最終將結果存儲在字符串中。

輸出僅僅是罰款,直到16,但16後的順序重演,

所需的輸出:

1,2,3,4,5,6,7,8, 9,10,11,12,13,14,15,16,17,18,19,20

電流輸出 1,2,3,4,5,6,7,8,9, 10,11,12,13,14,15,16,11,12,13,14,15

爲什麼會這樣呢? ???

這裏是我的代碼,

MOV CX,20 ;Number of Iterations 


MOV DX,1 



L1: 
    PUSH DX 
    ADD DX,30H 
    MOV AH,02H  ;PRINT Content of DX 
    INT 21H 
    POP DX 
    ADD DX,1 
    CMP DX,09d  ;If number is Greater than 9 jump to L2 
    JA L2 
LOOP L1 


    L2: 
     PUSH DX 
     MOV AX,DX 
     DAA   ;Convert to the Decimal 
     XOR AH,AH   ;SET AH to 0000 


     ROR AX,1  
     ROR AX,1  
     ROR AX,1  
     ROR AX,1  

     SHR AH,1 
     SHR AH,1 
     SHR AH,1 
     SHR AH,1 

     ADC AX,3030h 
     MOV BX,OFFSET Result 
     MOV byte ptr[BX],5   ; Length of the String 
     MOV byte ptr[BX+4],'$'  ;5th position of string , $=Terminator 
     MOV byte ptr[BX+3],AH  ;2nd Number onto 4th position 
     MOV byte ptr[BX+2],AL  ;3rd number onto 3rd Position 

     MOV DX,BX 
     ADD DX,02  ;1st 2 positions of String are type of string and  
            length respectively 
     MOV AH,09H ;to print the string 
     INT 21H   

     POP DX  
     ADD DX,1 

    LOOP L2 

MOV AH,4CH ;Return control to the DOS 
INT 21H 

P.S:我把幫助從這個圖表中瞭解數字。

http://www.cheat-sheets.org/saved-copy/ascii.png

+1

你應該緊湊化你的代碼,即G。使用'ror ax,4'一次,而不是四次'ror ax,1'。另外,並不是每個人都知道中斷調用是幹什麼的(我從來沒有在DOS下進行過彙編),如果你在這樣的代碼行中寫下簡短的註釋,就會更容易知道代碼的作用。 - 請儘可能多地移除空行。空行對於可讀性來說非常好,可以分隔邏輯代碼塊,但是多個後續的空行只是過分地擴展了列表。 – IdiotFromOutOfNowhere

+1

我在x64中使用DosBox,我認爲這就是爲什麼我無法直接使用ROR,4或SHR,4,我必須單獨使用它們。 和評論已添加 – micheller

+1

IIRC,你正在使用TASM,對不對?從我的英特爾手冊中可以看出,該彙編程序可能是一個缺陷,即通過立即旋轉/移位也可以以16位模式工作。無論如何,'mov word ptr [BX + 2],AX'怎麼辦 - 會有用嗎? ;-) – IdiotFromOutOfNowhere

回答

3

只是給它一個嘗試,雖然我不知道,我不能很快地進行測試。

但我不推薦使用兩個循環,而是使用一個數字。

此外,我覺得問題與​​指令有關,我不習慣這種指令,因爲它在64位模式下不受支持。

無論如何,這裏就是我想要做的:

 mov cx,20 
     mov al,1 
     mov bl,10  ; divisor 
     mov bp,offset Result ; no need to load this in the loop!!! 

L1: mov dx,ax  ; save to register, not to stack 
     cmp ax,09d 
     ja L2   ; number has two digits 
     add al,30h  ; ASCII addend 

     ; insert your output code here 

     jmp L3   ; jump over the two digit code 
L2: xor ah,ah 
     div bl   ; divides AX by ten (no rotate or shift needed) 
         ; quotient in AL, remainder in AH (correct order for little endian) 
     add ax,3030h 

     ; insert your output code here (note that the buffer/string address is loaded to BP) 

L3: mov ax,dx 
     inc ax 
     loop L1 

     ; done 

如果你不介意,如果一個位數字有一個前導零,這將會是更容易。

div指令比daarorshr可能更貴,但你的四循環/移位會更差: -/

(正如我所說的,我不能嘗試...離開這向你敞開......如果它不工作,只是反問)

[更新:

另一種方法,特別是在這個數字分隔這個微不足道的情況下,可以省掉div,將數字大於9的數字加上6即可。即10d = 0ah - (+ 6) - > 16d = 10h;這也是daa),那麼你可以與之前使用的旋轉/移位組合相處。

更妙的是增加246,然後AX,之後,您可以簡單地使用ror ax,8(或rol —不會在這種情況下問題),我。即10d = 0ah - (+ 246) - > 256d = 100h,以及15d = 0fh - (+ 246) - > 261 = 105h。分別旋轉0001h或0501h,加3030h,就完成了。

/更新]

[更新級別=「2」

什麼好玩的......其實我打算把它寫在第一級更新,卻忘了它在某種程度上:通過代替rol玲8,或—如果您TASM真的不立即進行—八次由一個滾動支持rol玲,你當然也可以利用xchg指令,該指令交換寄存器之間的值,在這種情況下

xchg al,ah 

會做交換這兩個寄存器內容的工作。

還有一個bswap指令用於反轉寄存器內的字節順序,但它顯然僅適用於32位寬度的寄存器。

/更新]

+1

這不適用於第20位數字, ; 20d = 14h - (+ 6) - > 26d = 1Ah – micheller

+0

是的:)但我真的很感謝你的努力,我簡化它, 每個值從0A到19我們都要添加6d,同樣的下一個10個值我們不需要添加6d,而是我們需要添加12d,接下來的10個值我們需要添加18d等等:) 在這裏你去:) \t \t \t; 10D = 0AH - (+ 6) - > 16D = 10H \t \t \t; 20D = 14H - (+ 12) - > 32D = 20H \t \t \t; 30D = 1Eh - (+ 18) - > 48h = 30h – micheller

3

8086代碼只允許立即數1(或Cl)爲上移和旋轉的計數。要啓用286代碼,請告訴文件頂部的Tasm「.286」。這是一個猜測。

我記得我以前在人打印兩位數字的方式:

aam 
add ax, 3030h 
xchg al, ah 
int 29h 
mov al, ah 
int 29h 
0
.model small 
.stack 100 
.code 
     mov ax, 0ffffh   ; hex number to find it's bcd 
     mov  bx, 0000 
     mov  dh, 0 
l9 :  cmp  ax, 10000  ; if ax>10000 
     jb  l2 
     sub  ax, 10000  ; subtract 10000 
     inc  dh    ; add 1 to dh 
     jmp  l9 
l2 :  cmp  ax, 1000  ; if ax>1000 
     jb  l4 
     sub  ax, 1000 
     add  bx, 1000h  ; add 1000h to result 
     jmp  l2 
l4 :  cmp  ax, 100  ; if ax>100 
     jb  l6 
     sub  ax, 100 
     add  bx, 100h   ; add 100h to result 
     jmp  l4 
l6 :  cmp  ax, 10  ; if ax>10 
     jb  l8 
     sub  ax, 10 
     add  bx, 10h   ; add 10h to result 
     jmp  l6 
l8 :  add  bx, ax  ; add remainder 
           ; to result 
     mov  ah, 02    
     mov  cx, 0204h  ; Count to display 
           ; 2 digits 
     go:  rol dh, cl 
     mov  dl, dh 
     and  dl, 0fh 
     add  dl, 30h   ; display 2 msb digits  
     int  21h 
     dec  ch 
     jnz  go 
     mov  ch, 04h   ; Count of digits to be 
           ; displayed 
     mov  cl, 04h   ; Count to roll by 4 bits 
l12:  rol  bx, cl  ; roll bl so that msb 
           ; comes to lsb     
     mov  dl, bl   ; load dl with data to be 
           ; displayed 
     and  dl, 0fH   ; get only lsb 
     cmp  dl, 09   ; check if digit is 0-9 or letter A-F  
     jbe  l14 
     add  dl, 07   ; if letter add 37H else only add 30H 
l14:  add  dl, 30H 
     mov  ah, 02   ; Function 2 under INT 21H  (Display character) 
     int  21H 
     dec  ch    ; Decrement Count 
     jnz  l12 
     mov  ah, 4cH   ; Terminate Program 
     int  21H 
end 
+1

歡迎來到StackOverflow,您可能想在閱讀之前閱讀[如何發佈一個好答案](http://stackoverflow.com/help/how-to-answer)。給出一些上下文來解釋爲什麼您發佈了該代碼以及它做了什麼,還考慮花時間設置您的答案的格式,以便讀者輕鬆理解。 – Nacho