难以概念化两个汇编程序

时间:2015-05-05 18:42:27

标签: assembly

以下两个项目是我几周前参加考试的问题,但我没有得到充分的信任。我无法弄清楚如何以任何其他方式做到这一点。我没有他们的原始代码,但我想知道你们/女孩是否可以告诉我你将如何做到这一点的例子,以便我能为下一次测试做好更充分的准备。如果你能解释你的程序是如何工作的,那么也将非常感激。谢谢!

1。)写一个程序输出你的名字10次,每次向下对角方向移动,左边写。使用循环。

鲍勃

(空格)鲍勃

(空格)(空间)鲍勃

我尝试通过在每次添加更多空格打印字符串之前添加空格来解决这个问题。

2。)输入5个数字,一个数组中的一个数字。打印输入的最高值和输入的值。

这个我实际上做得很好,我只是想知道如何在输入时显示。

再次感谢您提供的任何帮助。我试着环顾四周,找不到符合这些要求的ASM问题。

编辑:使用x86处理器和MASM。我们的课本如下,http://kipirvine.com/asm/gettingStartedVS2012/index.htm#tutorial32

1 个答案:

答案 0 :(得分:0)

我得到了两个测试题的答案。

接下来是您的程序#1的代码,算法如下:

scounter = 1;
for ( ncounter = 10; ncounter > 0; ncounter-- )
{ for ( cx = scounter; cx > 0; cx-- )
     printf( ' ' );
  scounter++;         // ANOTHER BLANK SPACE. STRING WILL MOVE TO THE RIGHT.
  printf( 'Bob Wrath' );
  printf( '\n' );
}

这很简单:两个计数器,一个用于名称,另一个用于空格。名称计数器是反向计数器(减少),空格计数器是正常的(增加)。现在汇编中的算法是用EMU8086制作的,但它与MASM的代码几乎相同(只需改变' $' by 0和DB by BYTE)。我使用注释作为小块代码的标题,使它们易于理解:

.stack 100h

.data

myname   DB 'Bob Wrath$'
space    DB ' $'        ;BLANK SPACE.
break    DB 13,10,'$'   ;LINE BREAK.
ncounter DW ?           ;COUNTER FOR NAMES.
scounter DW ?           ;COUNTER FOR SPACES.

.code

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

;INITIALIZE COUNTERS.  
  mov  ncounter, 10     ;DISPLAY 10 NAMES.
  mov  scounter, 1      ;START WITH 1 SPACE TO THE LEFT.

names:

;DISPLAY SPACES BEFORE THE STRING.
  mov  cx, scounter     ;NUMBER OF SPACES TO DISPLAY.
spaces:
  mov  dx, offset space
  call printf      
  loop spaces           ;CX-1. IF CX > 0 JUMP TO SPACES.
;INCREASE SPACES-COUNTER FOR THE NEXT ROUND.
  inc  scounter         

;DISPLAY NAME.             
  mov  dx, offset myname
  call printf

;DISPLAY LINE BREAK.              
  mov  dx, offset break
  call printf           ;DISPLAY LINE BREAK.

;CHECK IF NAMES-COUNTER IS 0.
  dec  ncounter         ;NCOUNTER - 1.
  jnz  names            ;IF (NCOUNTER != 0) JUMP TO NAMES.  

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

;-----------------------------------------
;PARAMETER : DX POINTING TO '$' FINISHED STRING.
proc printf
  mov  ah, 9
  int  21h
  ret
endp

现在节目#2。我再次使用EMU8086,这就是为什么我使用MASM可能不需要的一些程序(string2number,dollars,number2string)。该算法非常简单:从键盘中捕获5个(或任意多个)数字,将每个捕获的数字与最高值进行比较(非常重要:第一个最高值为0,这是必要的要找到最高,找到最低的第一个值应该是一个非常高的数字,比如32767,得到它?这样,第一个输入的数字会更高),最后,它显示的数字最高。请注意,我没有使用数组,因为它是不必要的,所解释的算法让我们在没有数组帮助的情况下找到最高数字:

.stack 100h

.data

counter dw ?

msj1    db 'Enter a number: $'
msj2    db 'The highest number is: $'
break   db 13,10,'$'

str     db 6                ;MAX NUMBER OF CHARACTERS ALLOWED (5).
        db ?                ;NUMBER OF CHARACTERS ENTERED BY USER.
        db 6 dup (?)        ;CHARACTERS ENTERED BY USER. 

highest dw 0        

buffer  db 6 dup(?)

.code

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

;-----------------------------------------
;CAPTURE 5 NUMBERS AND DETERMINE THE HIGHEST.

  mov  counter, 5           ;HOW MANY NUMBERS TO CAPTURE.
enter_numbers:                          

;DISPLAY MESSAGE.
  mov  dx, offset msj1
  call printf

;CAPTURE NUMBER AS STRING.
  mov  dx, offset str
  call scanf

;DISPLAY LINE BREAK.
  mov  dx, offset break
  call printf

;CONVERT CAPTURED NUMBER FROM STRING TO NUMERIC.
  mov  si, offset str       ;PARAMETER (STRING TO CONVERT).
  call string2number        ;NUMBER RETURNS IN BX.

;CHECK IF CAPTURED NUMBER IS THE HIGHEST.
  cmp  highest, bx  
  jae  ignore               ;IF (HIGHEST >= BX) IGNORE NUMBER.
;IF NO JUMP TO "IGNORE", CURRENT NUMBER IS HIGHER THAN "HIGHEST".  
  mov  highest, bx          ;CURRENT NUMBER IS THE HIGHEST.

ignore:  
;CHECK IF WE HAVE CAPTURED 5 NUMBERS ALREADY.
  dec  counter
  jnz  enter_numbers

;-----------------------------------------
;DISPLAY HIGHEST NUMBER.

;FIRST, FILL BUFFER WITH '$' (NECESSARY TO DISPLAY).
  mov  si, offset buffer
  call dollars

;SECOND, CONVERT HIGHEST NUMBER TO STRING.              
  mov  ax, highest
  mov  si, offset buffer
  call number2string

;THIRD, DISPLAY STRING.
  mov  dx, offset msj2
  call printf
  mov  dx, offset buffer
  call printf    

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

;-----------------------------------------
;PARAMETER : DX POINTING TO '$' FINISHED STRING.
proc printf
  mov  ah, 9
  int  21h
  ret
endp    

;-----------------------------------------
;PARAMETER : DX POINTING TO BUFFER TO STORE STRING.
proc scanf
  mov  ah, 0Ah
  int  21h
  ret
endp    

;------------------------------------------
;CONVERT STRING TO NUMBER.
;PARAMETER : SI POINTING TO CAPTURED STRING.
;RETURN    : NUMBER IN BX.

proc string2number
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
  inc  si ;POINTS TO THE NUMBER OF CHARACTERS ENTERED.
  mov  cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.                                         
  mov  ch, 0 ;CLEAR CH, NOW CX==CL.
  add  si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
  mov  bx, 0
  mov  bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:         
;CONVERT CHARACTER.                    
  mov  al, [ si ] ;CHARACTER TO PROCESS.
  sub  al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
  mov  ah, 0 ;CLEAR AH, NOW AX==AL.
  mul  bp ;AX*BP = DX:AX.
  add  bx, ax ;ADD RESULT TO BX. 
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
  mov  ax, bp
  mov  bp, 10
  mul  bp ;AX*10 = DX:AX.
  mov  bp, ax ;NEW MULTIPLE OF 10.  
;CHECK IF WE HAVE FINISHED.
  dec  si ;NEXT DIGIT TO PROCESS.
  loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.

  ret 
endp    

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

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

  ret
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.

proc number2string
  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
endp  

希望这可以帮助您进行下一次测试。