在程序集中从十进制数组转换为二进制数组的算法

时间:2015-05-08 17:31:05

标签: assembly x86-16

我正在做一个将decmial数字数组转换为二进制数组的项目 在汇编emu8086中,我知道如何做到这一点,但我需要更多帮助理解汇编中的数组,想法是取每个数字并将其转换为二进制,然后添加表示来获得结果

arrayD 1 2 3 4 
1->1000-> binary1
2->200 -> binary2
3->30 -> binary3
4-> binary4

add binary1,binary2,binary3,binary4 

用汇编语言可行吗?

2 个答案:

答案 0 :(得分:0)

以下是您的问题的解决方案,只需在EMU8086中进行复制粘贴并运行,完全注释以帮助您理解,它需要将一位数字存储在一个数组中,然后将每个数字乘以当时的幂(0。 .n,从右到左),并将这些数字存储在第二个数组中,最后显示所有内容(原始数组,新数组和总和):

.model small

.stack 100h

.data

arr1   dw 1,5,2,4,3         ;ARRAY OF ONE DIGIT NUMBERS.
arr2   dw 5 dup(?)          ;ARRAY FOR CONVERTED NUMBERS. 
len    dw 5                 ;LENGTH OF ARRAYS.
tot    dw ?                 ;SUM OF ALL CONVERTED NUMBERS.
msj1   db 'The first array is:',13,10,'$'
msj2   db 'The resulting array is:',13,10,'$'
msj3   db 'The total sum is:',13,10,'$'
buffer db 6 dup(?)          ;USED TO CONVERT NUMBERS TO STRING.
linbrk db 13,10,'$'         ;LINE BREAK.

.code
start:

;INITIALIZE DATA SEGMENT.
  mov  ax, @data
  mov  ds, ax

;TASKS.                    
  call process_arrays
  call sum_array
  call clear_screen
  call display_arr1
  call display_arr2
  call total_sum

;WAIT FOR ANY KEY.    
  mov  ah, 7
  int  21h

;FINISH PROGRAM.
  mov  ax, 4c00h
  int  21h

;-----------------------------------------
;MULTIPLY EACH NUMBER IN ARRAY1 BY 10^?, AND
;STORE THE RESULT IN ARRAY2. THE LAST NUMBER
;IS MULTIPLIED BY 10^0, THE PREVIOUS NUMBER
;IS MULTIPLIED BY 10^1, AND SO ON, EXAMPLE:
;   ARR1 = [ 1,5,2,4,3 ].
;PROCESS = 3 * 10^0
;          4 * 10^1
;          2 * 10^2
;          5 * 10^3
;          1 * 10^4
;   ARR2 = [ 10000,5000,200,40,3 ]. 

process_arrays proc

;INITIALIZATIONS.
  mov  cx, len              ;LENGTH OF ARRAYS.
  shl  cx, 1                ;CX*2, NECESSARY BECAUSE EVERY NUMBER IS 2 BYTES LONG.
  mov  si, offset arr1      ;SI POINTS TO FIRST NUMBER.
  add  si, cx               ;NOW SI POINTS BEYOND THE LAST NUMBER.
  sub  si, 2                ;NOW SI POINTS TO THE LAST NUMBER.
  mov  di, offset arr2      ;DI POINTS TO FIRST POSITION.
  add  di, cx               ;NOW DI POINTS BEYOND THE LAST POSITION.
  sub  di, 2                ;NOW DI POINTS TO THE LAST POSITION.
  mov  cx, len              ;REVERSE COUNTER (TO KNOW WHEN TO FINISH).
  mov  bp, 0                ;FIRST POWER OF 10: 10^0.

converting:

;CALCULATE 10^?.
  cmp  bp, 0
  je   first_time           ;SPECIAL CASE: 10^0.
  mov  ax, 10
  mul  bp                   ;AX * BP = 10*BP (10*1, 10*10, 10*100, 10*1000).
  mov  bp, ax               ;STORE RESULT OF MUL (AX) IN BP.
  jmp  not_first_time       ;THIS JUMP IS TO SKIP MOV BP, 1.
first_time: 
  mov  bp, 1                ;10^0 = 1.
not_first_time:  

;MULTIPLY CURRENT NUMBER BY 10^?.
  mov  ax, [ si ]           ;AX = CURRENT NUMBER.
  mul  bp                   ;AX * BP (CURRENT_NUMBER * 10^?).

;STORE RESULT IN THE OTHER ARRAY.
  mov  [ di ], ax

;MOVE TO NEXT POSITION IN ARRAYS. WE GO BACKWARDS BECAUSE WE MOVE
;FROM THE LEAST SIGNIFICANT DIGIT TO THE MOST (FROM RIGHT TO LEFT).
  sub  si, 2                ;MINUS 2 BECAUSE EACH NUMBER
  sub  di, 2                ;IS TWO BYTES LONG (DW).

  loop converting           ;CX--. IF (CX > 0) JUMP.

  ret
process_arrays endp    

;-----------------------------------------
;SUM ALL NUMBERS IN ARRAY2, EXAMPLE:
;   ARR2 = [ 10000,5000,200,40,3 ].
;PROCESS = 10000 + 5000 + 200 + 40 + 3 = 15.243.

sum_array proc
  mov  si, offset arr2
  mov  cx, len              ;REVERSE COUNTER.
  mov  ax, 0                ;TOTAL.
sums:  
  add  ax, [ si ]           ;SUM CURRENT NUMBER.
  add  si, 2                ;NEXT NUMBER IN ARRAY (2 BECAUSE NUMBER IS DW).
  loop sums                 ;CX--. IF (CX > 0) JUMP.
  mov  tot, ax

  ret
sum_array endp

;-----------------------------------------

display_arr1 proc

;DISPLAY MESSAGE.    
  mov  dx, offset msj1    
  call printf

;DISPLAY NUMBERS.
  mov  si, offset arr1  
  mov  cx, len
displ_a1:
  mov  ax, [ si ]           ;GET CURRENT NUMBER.
  push cx                   ;PRESERVE COUNTER (IT WILL BE MODIFIED).
  push si                   ;PRESERVE POINTER (IT WILL BE MODIFIED).
;CONVERT CURRENT NUMBER TO STRING.              
  mov  si, offset buffer    ;PARAMETER FOR NUMBER2STRING.
  call number2string        ;CONVERT AX IN STRING POINTED BY SI.        
;DISPLAY STRING.  
  mov  dx, offset buffer    ;STRING TO DISPLAY.   
  call printf
  mov  dx, offset linbrk    ;LINE BREAK.
  call printf

  pop  si                   ;RESTORE POINTER.
  pop  cx                   ;RESTORE COUNTER.
  add  si, 2                ;NEXT NUMBER IN ARRAY (2 BECAUSE NUMBER IS DW).
  loop displ_a1             ;CX--. IF (CX > 0) JUMP.

  ret
display_arr1 endp

;-----------------------------------------

display_arr2 proc

;DISPLAY MESSAGE.    
  mov  dx, offset msj2    
  call printf

;DISPLAY NUMBERS.
  mov  si, offset arr2  
  mov  cx, len
displ_a2:
  mov  ax, [ si ]           ;GET CURRENT NUMBER.
  push cx                   ;PRESERVE COUNTER (IT WILL BE MODIFIED).
  push si                   ;PRESERVE POINTER (IT WILL BE MODIFIED).
;CONVERT CURRENT NUMBER TO STRING.              
  mov  si, offset buffer    ;PARAMETER FOR NUMBER2STRING.
  call number2string        ;CONVERT AX IN STRING POINTED BY SI.        
;DISPLAY STRING.  
  mov  dx, offset buffer    ;STRING TO DISPLAY.   
  call printf
  mov  dx, offset linbrk    ;LINE BREAK.
  call printf

  pop  si                   ;RESTORE POINTER.
  pop  cx                   ;RESTORE COUNTER.
  add  si, 2                ;NEXT NUMBER IN ARRAY (2 BECAUSE NUMBER IS DW).
  loop displ_a2             ;CX--. IF (CX > 0) JUMP.

  ret
display_arr2 endp

;-----------------------------------------

total_sum proc

;CONVERT SUM TO STRING.              
  mov  ax, tot              ;PARAMETER FOR NUMBER2STRING (NUMBER TO CONVERT).
  mov  si, offset buffer    ;PARAMETER FOR NUMBER2STRING (DESTINATION STRING).
  call number2string        ;CONVERT AX IN STRING POINTED BY SI.        

;DISPLAY MESSAGE.    
  mov  dx, offset msj3
  call printf

;DISPLAY STRING.  
  mov  dx, offset buffer    ;STRING TO DISPLAY.   
  call printf

  ret
total_sum endp    

;-----------------------------------------
;PARAMETER : DX POINTING TO '$' FINISHED STRING.

printf proc
  mov  ah, 9
  int  21h
  ret
printf endp    

;-----------------------------------------

clear_screen proc
  mov  ah, 0
  mov  al, 3
  int  10H
  ret
clear_screen endp

;------------------------------------------
;CONVERT A NUMBER IN STRING.
;ALGORITHM : EXTRACT DIGITS ONE BY ONE, STORE
;THEM IN STACK, THEN EXTRACT THEM IN REVERSE
;ORDER TO CONSTRUCT STRING (STR).
;PARAMETERS : AX = NUMBER TO CONVERT.
;             SI = POINTING WHERE TO STORE STRING.
number2string proc
;FILL BUFFER WITH '$' (NECESSARY TO DISPLAY).    
  push si                   ;PRESERVE POINTER (IT WILL BE MODIFIED).
  call dollars              ;FILL BUFFER WITH '$' (NECESSARY TO DISPLAY). 
  pop  si                   ;RESTORE POINTER.

  mov  bx, 10               ;DIGITS ARE EXTRACTED DIVIDING BY 10.
  mov  cx, 0                ;COUNTER FOR EXTRACTED DIGITS.
cycle1:       
  mov  dx, 0                ;NECESSARY TO DIVIDE BY BX.
  div  bx                   ;DX:AX / 10 = AX:QUOTIENT DX:REMAINDER.
  push dx                   ;PRESERVE DIGIT EXTRACTED FOR LATER.
  inc  cx                   ;INCREASE COUNTER FOR EVERY DIGIT EXTRACTED.
  cmp  ax, 0                ;IF NUMBER IS
  jne  cycle1               ;NOT ZERO, LOOP. 
;NOW RETRIEVE PUSHED DIGITS.
cycle2:  
  pop  dx        
  add  dl, 48               ;CONVERT DIGIT TO CHARACTER.
  mov  [ si ], dl
  inc  si
  loop cycle2  

  ret
number2string endp  

;------------------------------------------
;FILLS VARIABLE WITH '$'.
;USED BEFORE CONVERT NUMBERS TO STRING, BECAUSE
;THE STRING WILL BE DISPLAYED.
;PARAMETER : SI = POINTING TO STRING TO FILL.

dollars proc
  mov  cx, 6
six_dollars:      
  mov  bl, '$'
  mov  [ si ], bl
  inc  si
  loop six_dollars

  ret
dollars endp  

end start

我对array1(1,5,2,4,3)中的数字进行了硬编码,您可以更改此数字(但请注意,总和不得超过65535)。这是做什么的(例子):

ARRAY1 = [ 1,5,2,4,3 ].
PROCESS = 3 * 10^0
          4 * 10^1
          2 * 10^2
          5 * 10^3
          1 * 10^4
ARRAY2 = [ 10000,5000,200,40,3 ]. 
SUM    = 15243

我不确定是否需要其他进程:将每个数量的array2转换为二进制格式并再次显示,请告诉我。

答案 1 :(得分:-1)

model small 
.stack 100h .data result db ? 
array1 db 10,20,30,40 
.code  start: 
movax,@data 
movds,ax 

movsi,offset array1 movcx,lengthof array1 
mov al,0 L1: add al,[si] incsi 
Loop L1 
movresult,al 

movdx,offset result  
mov ah,9 
int 21h 

mov ah,4ch int 21h 
end start