【问题标题】:Creating a function in assembly language (TASM)用汇编语言 (TASM) 创建函数
【发布时间】:2012-09-23 19:28:06
【问题描述】:

我想使用循环打印前 20 个数字。

打印前九个数字绝对没问题,因为十六进制和十进制代码是相同的,但是从第 10 个数字开始,我必须将每个数字转换为相应的代码,然后将其转换并存储为字符串并最终显示它

也就是说,

If (NUMBER > 9)
ADD 6D
;10d = 0ah --(+6)--> 16d = 10h
IF NUMBER IS > 19
ADD 12D
;20d = 14h --(+12)--> 32d = 20h

然后对每个数字进行旋转移位,得到想要的输出数字,即

DAA          # let al = 74h = 0111.0100

XOR AH,AH    # ah = 0 (Just in case it wasn't)
             # ax = 0000.0000.0111.0100

ROR AX,4     # ax = 0100.0000.0000.0111 = 4007h
SHR AH,4     # ax = 0000.0100.0000.0111 = 0407h
ADD AX,3030h # ax = 0011.0100.0011.0111 = 3437h = ASCII "74" (Reversed due to little endian)

然后将结果存入字符串并显示出来,即

MOV BX,OFFSET Result    ;Let Result is an empty string
MOV byte ptr[BX],5      ;Size of the string
MOV byte ptr[BX+4],'$'  ;String terminator
MOV byte ptr[BX+3],AH   ;storing number
MOV byte ptr[BX+2],AL

MOV DX,BX
ADD DX,02  ;Displaying the result
MOV AH,09H ;Interrupt 21 service to display string
INT 21H

这是带有适当注释的完整代码,

MOV CX,20  ;Number of iterations
MOV DX,0   ;First value of the sequence

L1:

    PUSH DX
    ADD DX,30H  ; 30H is equal to 0 in hexadecimal , 31H = 1 and so on
    MOV AH,02H  ; INTERRUPT Service to print the DX content
    INT 21H
    POP DX
    ADD DX,1
    CMP DX,09   ; if number is > 9 i.e 0A then go to L2
    JA L2
LOOP L1


L2:
    PUSH DX
    MOV AX,DX
    CMP AX,14H   ;If number is equal to 14H(20) then Jump to L3
    JE L3
    ADD AX,6D    ;If less than 20 then add 6D
    XOR AH,AH    ;Clear the content of AH

    ROR AX,4     ;Rotating and Shifting for to properly store
    SHR AH,4

    ADC AX,3030h
    MOV BX,OFFSET Result
    MOV byte ptr[BX],5
    MOV byte ptr[BX+4],'$'
    MOV byte ptr[BX+3],AH
    MOV byte ptr[BX+2],AL

    MOV DX,BX
    ADD DX,02
    MOV AH,09H
    INT 21H
    POP DX
    ADD DX,1
LOOP L2

;If the number is equal to 20 come here, ->
; Every step is repeated here just to change 6D to 12D

L3:
    ADD AX,12D
    XOR AH,AH

    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
    MOV byte ptr[BX+4],'$'
    MOV byte ptr[BX+3],AH
    MOV byte ptr[BX+2],AL

    MOV DX,BX
    ADD DX,02
    MOV AH,09H
    INT 21H

有什么合适的方法可以做到这一点,创建一个函数并使用 if/else(跳转)来获得所需的输出,而不是一次又一次地重复代码?

伪代码:

VAR = 6
IF Number is > 9
ADD AX,VAR
Else IF Number is > 19
ADD AX,(VAR*2)
ELSE IF NUMBER is > 29
ADD AX,(VAR*3)

【问题讨论】:

  • IF/ELSE 直接转换为 CMP/Jcc/JMP。我不确定您是如何到达30H is equal to 1 in hexadecimal 的。此外,函数 2 不需要字符串的长度,它会打印所有内容,直到到达 "$"。
  • 抱歉写错了 (30h = 0) ,你能给我一个两行代码示例我们如何使用 CMP/JCC/JMP 吗?或者创建一个函数,我只是要求一个例子
  • 所有IF COND A ELSE B 所做的只是执行一段代码(A,如果COND 为真)或另一段代码(B,如果COND 为假)。所以你用CMP检查条件。然后使用适当的Jcc 直接在IF (A) 之后或ELSE (B) 之后立即执行代码。不用说,A 不应该以在B 中继续执行而结束,它必须跳过B。你有一个或两个,而不是两者。
  • 我真的认为你会更喜欢“aam”而不是“daa”(除非它是“作业”的一部分)。我怀疑你是否想要“adc”,除非你真的想添加进位标志 - 使用普通的“add”。请注意,一个字节可能是三位数字,此代码仅适用于两位!适用于“最多 20 个”......也适用于“时间”数字。 (否则重复使用“div”...)

标签: function assembly x86 tasm


【解决方案1】:

所以您只想将 0 ... 20 打印为 ASCII 字符?看起来您了解数字被标识为 0x30 ... 0x39 表示“0”到“9”,因此您可以使用整数除法来生成十位数字的字符:

我通常使用 C,但转换为汇编程序不应该太复杂,因为这些都是基本操作并且没有函数调用。

int i_value = 29;
int i_tens = i_value/10; //Integer division! 29/10 = 2, save for later use
char c_tens = '0' + i_tens;
char c_ones = '0' + i_value-(10*i_tens); // Subtract N*10 from value

输出将是c_tens = 0x32, c_ones = 0x39。您应该能够使用一对寄存器轻松地将其包装在循环中。

伪代码

regA <- num_iterations //For example, 20
regB <- 0 //Initialize counter register

LOOP:
    //Do conversion for the current iteration.
    //Manipulate bytes for output as necessary.
    regB <- regB +1
    branch not equal regA, regB LOOP

【讨论】:

  • Ryan 是对的...(尽管他的语法不是很清楚;-) ...正如我在另一个问题中指出的那样,将十进制数字彼此分开的最简单方法是使用div &lt;reg&gt; 其中&lt;reg&gt; 对应于任何字节寄存器(其内容为 10d/0ah),实际数字保存在寄存器 AX 中。这样,您最终将得到 AH 中的较低有效数字(除法的余数)和 Al(实际商)中的较高有效数字。使用div 似乎是唯一(基本)分隔数字而不关心 n*(10h-10d) 距离的方法。
【解决方案2】:

以下代码从 0 到 99 计数(ax 包含 ASCII 数字):

count proc
      mov cx, 100 ; loop runs the times specified in the cx register
      xor bx, bx ; set counter to zero
      print:
      mov ax, bx
      aam ; Converts binary to unpacked BCD
      xor ax, 3030h ; Converts upacked BCD to ASCII
      ; Print here (ax now contains the numer in ASCII representation)
      inc bx ; Increase counter
      loop print
      ret
count endp

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 1970-01-01
    • 2019-02-13
    • 2013-04-21
    • 1970-01-01
    相关资源
    最近更新 更多