如何在装配体中乘两个大数字打印出结果?
我是新来的程序集,我一直在尝试创建一个程序,每个数字最多需要3位数字([numR],[numG],[numB]),然后执行公式:(65536 * [numR] + 256 * [numG] + [numB]),最后打印出结果。如何在装配体中乘两个大数字打印出结果?
我已经编写了大部分程序(我已经能够从用户获得每个数字的输入并将其存储在上面显示的3个变量中),但我似乎无法找到一种方法执行公式,主要是因为在乘以大数字时,结果会在寄存器dx和ax之间分开。
我不知道怎么会这样的帮助,但这里是到目前为止我的代码:
;------------------------------------------
; PURPOSE : Color Code Generator
; SYSTEM : Turbo Assembler Ideal Mode
; AUTHOR : Re'em Kishnevsky
;------------------------------------------
IDEAL
MODEL small
STACK 256
DATASEG
include 'start.txt'
count db 0
num db ?, ?, ?
numR dw ?
numG dw ?
numB dw ?
numFinal dd ?
CODESEG
Start:
mov ax, @data
mov ds, ax
;Sets text mode
mov ah, 0
mov al, 2 ; 3
int 10h
;Sets cursor position 0,0
mov dh, 0
mov dl, 0
call SetCursorPosition
;Prints initial message
mov dx, offset msg
mov ah, 09h
int 21h
call ReadKeyInput
;Sets cursor position 0,0
mov dh, 0
mov dl, 0
call SetCursorPosition
;Paints the screen red
mov bl, 01000000b
call PaintScreen
;Prints RED message
mov bp, offset red
mov bl, 01001111b
mov cx, 31
mov dh, 10
mov dl, 24
call PrintMessage
;Sets cursor position 35,12
mov dh, 12
mov dl, 35
call SetCursorPosition
mov bl, 01001111b
call DetermineNumber
cmp [count], 1
je R1Digit
cmp [count], 2
je R2Digit
dec si
push [si]
pop [numR]
dec si
mov al, 10
mul [byte ptr si]
add [numR], ax
dec si
mov al, 100
mul [byte ptr si]
add [numR], ax
jmp Phase_green
R1Digit:
dec si
push [si]
pop [numR]
jmp Phase_green
R2Digit:
dec si
push [si]
pop [numR]
dec si
mov al, 10
mul [byte ptr si]
add [numR], ax
Phase_green:
;Sets cursor position 0,0
mov dh, 0
mov dl, 0
call SetCursorPosition
;Paints the screen green
mov bl, 00100000b
call PaintScreen
;Prints GREEN message
mov bp, offset green
mov bl, 00101111b
mov cx, 33
mov dh, 10
mov dl, 24
call PrintMessage
;Sets cursor position 35,12
mov dh, 12
mov dl, 35
call SetCursorPosition
mov [count], 0
mov bl, 00101111b
call DetermineNumber
cmp [count], 1
je G1Digit
cmp [count], 2
je G2Digit
dec si
push [si]
pop [numG]
dec si
mov al, 10
mul [byte ptr si]
add [numG], ax
dec si
mov al, 100
mul [byte ptr si]
add [numG], ax
jmp Phase_blue
G1Digit:
dec si
push [si]
pop [numG]
jmp Phase_blue
G2Digit:
dec si
push [si]
pop [numG]
dec si
mov al, 10
mul [byte ptr si]
add [numG], ax
Phase_blue:
;Sets cursor position 0,0
mov dh, 0
mov dl, 0
call SetCursorPosition
;Paints the screen blue
mov bl, 00010000b
call PaintScreen
;Prints GREEN message
mov bp, offset blue
mov bl, 00011111b
mov cx, 32
mov dh, 10
mov dl, 24
call PrintMessage
;Sets cursor position 35,12
mov dh, 12
mov dl, 35
call SetCursorPosition
mov [count], 0
mov bl, 00011111b
call DetermineNumber
cmp [count], 1
je B1Digit
cmp [count], 2
je B2Digit
dec si
push [si]
pop [numB]
dec si
mov al, 10
mul [byte ptr si]
add [numB], ax
dec si
mov al, 100
mul [byte ptr si]
add [numB], ax
jmp Phase_final
B1Digit:
dec si
push [si]
pop [numB]
jmp Phase_final
B2Digit:
dec si
push [si]
pop [numB]
dec si
mov al, 10
mul [byte ptr si]
add [numB], ax
Phase_final:
mov ax, 32768 ;This is where I want the formula calculation to be performed.
mul [numR] ;as you can see, I divided 65536 by two so it could fit in register ax
Exit:
mov ax, 4C00h
int 21h
;-----------------------------------------
;DetermineNumber - Determines the number input from the user
;-----------------------------------------
;Input:
; bl <- attribute of character
;Output:
; [num] <- (digit 1, digit 2, digit 3) ,Written number
;Registers:
; ah, al, bh, bl, dh, dl, cx, si
;-----------------------------------------
Proc DetermineNumber
mov si, offset num
@@Determine_number:
call ReadKeyInput
cmp al, 48
je @@0
cmp al, 49
je @@1
cmp al, 50
je @@2
cmp al, 51
je @@3
cmp al, 52
je @@Mid1_4
cmp al, 53
je @@Mid1_5
cmp al, 54
je @@Mid1_6
cmp al, 55
je @@Mid1_7
cmp al, 56
je @@Mid1_8
cmp al, 57
je @@Mid1_9
cmp al, 27
je @@Mid1_ESC
cmp al, 13
je @@Mid1_Enter
@@0: cmp [count], 3
je @@Determine_number
mov [byte ptr si], 0
inc [count]
inc si
mov al, '0'
call PrintCharacter
jmp @@Determine_number
@@1: cmp [count], 3
je @@Determine_number
mov [byte ptr si], 1
inc [count]
inc si
mov al, '1'
call PrintCharacter
jmp @@Determine_number
@@2: cmp [count], 3
je @@Determine_number
mov [byte ptr si], 2
inc [count]
inc si
mov al, '2'
call PrintCharacter
jmp @@Determine_number
@@3: cmp [count], 3
je @@Determine_number
mov [byte ptr si], 3
inc [count]
inc si
mov al, '3'
call PrintCharacter
jmp @@Determine_number
@@Mid1_Determine_number: jmp @@Determine_number
@@Mid1_4: jmp @@4
@@Mid1_5: jmp @@5
@@Mid1_6: jmp @@6
@@Mid1_7: jmp @@Mid2_7
@@Mid1_8: jmp @@Mid2_8
@@Mid1_9: jmp @@Mid2_9
@@Mid1_ESC: jmp @@Mid2_ESC
@@Mid1_Enter: jmp @@Mid2_Enter
@@4: cmp [count], 3
je @@Mid1_Determine_number
mov [byte ptr si], 4
inc [count]
inc si
mov al, '4'
call PrintCharacter
jmp @@Mid1_Determine_number
@@5: cmp [count], 3
je @@Mid1_Determine_number
mov [byte ptr si], 5
inc [count]
inc si
mov al, '5'
call PrintCharacter
jmp @@Mid1_Determine_number
@@6: cmp [count], 3
je @@Mid1_Determine_number
mov [byte ptr si], 6
inc [count]
inc si
mov al, '6'
call PrintCharacter
jmp @@Mid1_Determine_number
@@Mid2_Determine_number: jmp @@Determine_number
@@Mid2_5: jmp @@5
@@Mid2_6: jmp @@6
@@Mid2_7: jmp @@7
@@Mid2_8: jmp @@8
@@Mid2_9: jmp @@9
@@Mid2_ESC: jmp @@ESC
@@Mid2_Enter: jmp @@Enter
@@7: cmp [count], 3
je @@Mid2_Determine_number
mov [byte ptr si], 7
inc [count]
inc si
mov al, '7'
call PrintCharacter
jmp @@Mid2_Determine_number
@@8: cmp [count], 3
je @@Mid2_Determine_number
mov [byte ptr si], 8
inc [count]
inc si
mov al, '8'
call PrintCharacter
jmp @@Mid2_Determine_number
@@9: cmp [count], 3
je @@Mid2_Determine_number
mov [byte ptr si], 9
inc [count]
inc si
mov al, '9'
call PrintCharacter
jmp @@Mid2_Determine_number
@@ESC: call EndProgram
@@Enter:
cmp [count], 0
je @@Mid2_Determine_number
ret
ENDP DetermineNumber
;-----------------------------------------
;ReadKeyInput - Reads key input
;-----------------------------------------
;Input:
; Keyboard key press
;Output:
; ah <- scan code, al <- ascii code
;Registers:
; ah, al
;-----------------------------------------
Proc ReadKeyInput
mov ah, 00h
int 16h
ret
ENDP ReadKeyInput
;----------------------------------------------------------------
;PaintScreen - Paints the screen in a specific color
;----------------------------------------------------------------
;Input:
; bl -> color
;Output:
; Printed message
;Registers:
; ah, al, bh, bl, cx
;----------------------------------------------------------------
PROC PaintScreen
mov ah, 09h
mov bh, 0 ; page number
mov cx, 2000 ; count of characters to write
mov al, '' ; character to write
int 10h
ret
ENDP PaintScreen
;----------------------------------------------------------------
;PrintMessage - Prints a message
;----------------------------------------------------------------
;Input:
; bp -> offset of message, bl -> attribute, dl -> Starting column, dh -> Starting row, cx -> length
;Output:
; Printed message
;Registers:
; ah, al, bh, cx, dx, es, bp
;----------------------------------------------------------------
PROC PrintMessage
mov ah, 13h ; video page number
mov bh, 0
mov al, 0 ; 0-3 indicating mode
push ds
pop es ; es:bp pointer to string to be written
int 10h
ret
ENDP PrintMessage
Proc EndProgram
mov dh, 0
mov dl, 0
call SetCursorPosition
mov bl, 0Fh
call PaintScreen
mov ax, 4C00h
int 21h
ret
ENDP EndProgram
;----------------------------------------------------------------
;SetCursorPosition - Sets Cursor Position
;----------------------------------------------------------------
;Input:
; dl -> Column, dh -> Row
;Output:
; Printed message
;Registers:
; ah, bh, dh, dl
;----------------------------------------------------------------
Proc SetCursorPosition
mov bh, 0
mov ah, 2h
int 10h
ret
ENDP SetCursorPosition
Proc PrintCharacter
mov ah, 09h
mov bh, 0 ; page number
mov cx, 1 ; count of characters to write
int 10h
inc dl
call SetCursorPosition
ret
ENDP PrintCharacter
END start
这里是start.txt的内容:
msg db "Press any key to continue"
red db "Please type in the value of RED"
green db "Please type in the value of GREEN"
blue db "Please type in the value of BLUE"
final db "Your color code is $"
处理器:Intel 8086,汇编:TASM
你应该停下来认识为什么那些RGB24位颜色使用那样的一些奇怪的公式65536 * R ...
作为计算机中的每个值,颜色也是按位编码的。在24b RGB(32b ARGB)格式中,每个颜色通道有8位(1字节)。 256 = 2 和65536 = 2 (1 = 2 当然)。
所以你不需要乘以任何东西,只需要移动值。您首先需要存储结果,结果至少为24位,通常使用32位,最高8位用作“填充”。
colorResult db 0, 0, 0, 0 ; B, G, R, (alfa/padding)
然后让我们说numR
,numG
,numB
已经包含了他们的价值观..因为他们被定义为WORD,存储的值可以是0-255范围之外,这下面的代码将“sanitize方法”通过简单截断它(即红色的值260将结束为R = 4(截断为8位))。
mov al,BYTE PTR [numB]
mov ah,BYTE PTR [numG] ; this is doing *256
; because AH is 8 bits "left" to the al
mov WORD PTR [colorResult],ax ; store first half of result
mov al,BYTE PTR [numR]
xor ah,ah ; set padding/alfa to 0
mov WORD PTR [colorResult+2],ax ; this is doing *65536
; because that +2 is 16 bits shift, which is *65536
完成。
为了使移位更加明显(如前例所示,它由字节偏移和al/ah构成隐藏),还有一个例子:在32b寄存器的保护模式下,经常需要做相反的操作,分解24b RGB值到通道:
; eax = 24b RGB (B is low 8 bits)
mov ebx,eax
shr ebx,8 ; ebx will be G, this is /256
mov ecx,eax
shr ecx,16 ; ecx will be R, this is /65536
mov edx,eax
shr edx,24 ; edx will be alpha, this is /16777216 (2**24)
; eax will be B
; all channels (eax, ebx, ecx, edx) already contain correct value in low 8 bits
; so now all is needed to mask out any other bits left in upper parts
movzx eax,al
movzx ebx,bl
movzx ecx,cl
; edx already contains only 8 bits of alpha, SHR did clear upper 24 bits
所以,想想值是如何编码的计算机,并通过2的幂如何乘法可以只通过移位位向左做(和移位位权无符号divison,签署差不多作品,除了-1/2,当SAR
转移而不是正确的划分时,它保持-1)。而且它是多么的方便,RGB被定义为8位值......这不是巧合,而是完全用单独的值来实现这种简单的操作。相反,存在例如16位RGB 5:6:5格式,这有助于节省视频/纹理存储器(每像素只有2个字节),但是任何颜色处理必须进行更多的移位+掩蔽获得特定的频道值,或将这些值组合成彩色。
编辑:当然没有机会适应24B到16B寄存器,所以你不能有最终的结果在ax
,这就是为什么我的第一个示例将最终32B颜色值到内存中,而不是到寄存器。
来加载回dx:ax
例如(二16B寄存器= 32B),你可以这样做:
mov ax,[colorResult] ; ax = B + G*256
mov dx,[colorResult+2] ; dx = R + alfa*256
或用80386+ CPU,你甚至可以在实模式下使用eax
,所以:
mov eax,[colorResult] ; eax = B + G*256 + R*65536 + (alfa<<24)
这是一种将字节拆分为单独寄存器的笨拙方式。更好:'movzx edx,al' /'shr eax,8' /'movzx ecx,al'/...无论如何,因为它被标记为8088.但8086系统没有24位RGB颜色,他们? :P –
@PeterCordes VGA调色板模式只有6:6:6 IIRC,但作为独立的字节访问,所以它是24b RGB,每个通道有2b的填充。一些SVGA卡具有完整的8:8:8色IIRC和24/32b“真彩色模式”...即使在286实模式下也可以访问。不要低估那么早的PC,它已经是野兽;)只是很慢的一个。 640k对每个人都足够了。这个例子故意作为移动和掩蔽的例子而笨拙。标签8088是OP没有引起足够重视(或缺乏OCD)的另一个例子,如文本中它是8086;):) – Ped7g
非常感谢您的帮助,我是新来的换班命令,所以我有一个很难理解你的例子。与此说,我明白,你可以很容易乘以2的幂数左移,所以我想我会创建一个四字变量来存储结果和工作在该变量,我试图做第一次计算(R * 65536)通过将[numR]的值放入qw变量中,并将其向左移动16次,但汇编程序不会让我这样做。我怎么解决这个问题? 这里是代码: push [numR] pop [word ptr结果] shl [结果],15 – Stonewow
当红色为0,绿色为1,蓝色为500时,你想要什么结果? 756? (通常这种24位格式的r/g/b值限于8位,即仅限于0-255,不是“三位数”)。 – Ped7g