您的位置:首页 > 编程语言

汇编语言醉汉走路代码分析(15)

2009-10-22 08:31 501 查看
 

来自于《Intel汇编语言程序设计》(第四版)第10章----结构和宏。

 

所谓醉汉走路,即在一个XY坐标的二维地图中,模拟一个醉汉走路的轨迹(原书中说的是一个喝醉了酒还未清醒的教授)。此处仍然用到了结构和宏,来看一下原书代码:

 

 

 

TITLE Drunkard's Walk                   (Walk.asm)

 

INCLUDE Irvine32.inc

WalkMax = 50

StartX = 25

StartY = 25

 

DrunkardWalk STRUCT

         path COORD WalkMax DUP(<0,0>)

         pathsUsed WORD 0

DrunkardWalk ENDS

 

DisplayPosition PROTO currX:WORD,currY:WORD

 

.data

aWalk DrunkardWalk <>

 

.code

main PROC

        mov esi,offset aWalk

        call TakeDrunkenWalk

        exit

main ENDP

 

 

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

TakeDrunkenWalk PROC

LOCAL currX:WORD,currY:WORD

;

; Take a walk in random direction (north ,south,east,west).

; Receives : ESI points to a DrunkardWalk structure

; Returns : the structure is initialized with random values

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

          pushad

; Point EDI to the array of  COORD objects.

          mov edi,esi

          add edi,OFFSET DrunkardWalk.path

          mov ecx,WalkMax                 ; loop count

          mov currX,StartX                   ; current X-location

          mov currY,StartY                    ; current Y-location

 

Again:

          ; insert current location in array

          mov ax,currX

          mov (COORD PTR [edi]).X , ax

          mov ax,currY

          mov (COORD PTR [edi]).Y , ax

 

          INVOKE DisplayPosition , currX , currY

          mov eax,4            ; choose a direction (0-3)

          call RandomRange

         

          .IF eax==0                    ; north

          inc currY

          .ELSEIF eax==1            ; south

          dec currY

          .ELSEIF eax==2            ; west

          dec currX

          .ELSE                            ; east (eax = 3)

           inc currX

          .ENDIF

 

          add edi,TYPE COORD    ; point to next COORD

          loop Again

 

Finish:

          mov (DrunkardWalk PTR [esi]).pathsUsed,WalkMax

          popad

          ret

TakeDrunkenWalk ENDP

 

 

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

DisplayPosition PROC currX:WORD,currY:WORD

; Display the current X and Y position.

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

.data

commaStr BYTE ",",0

.code

           pushad

           movzx eax,currX                          ; current X postion

           call WriteDec

           mov edx, OFFSET commaStr        ; "," string

           call WriteString

           movzx eax,currY                          ; current Y position

           call WriteDec

           call Crlf

           popad

           ret

DisplayPosition ENDP

END main

 

 

 

让我们用代码注释来具体分析:

 

 

 

 

TITLE Drunkard's Walk                   (Walk.asm)

 

 

INCLUDE Irvine32.inc                              ; 包含了作者的库,许多函数就来自于这个库,比如WriteString,WriteDec,RandomRange函数等等

WalkMax = 50                                         ; 最多能行走的步数

StartX = 25                                             ; 开始X坐标

StartY = 25                                             ; 开始Y坐标

 

DrunkardWalk STRUCT                              ; 一个DrunkardWalk 结构

         path COORD WalkMax DUP(<0,0>)  ; 一个存储行走过得坐标位置的COORD类型的结构数组

         pathsUsed WORD 0                         ; 存储行走过的步数

DrunkardWalk ENDS                                 ; 结构结束

 

DisplayPosition PROTO currX:WORD,currY:WORD        ;  DisplayPosition 函数的原型声明

 

.data

aWalk DrunkardWalk <>                            ; 声明了一个DrunkardWalk 结构变量aWalk

 

.code

main PROC                                                 ; 开始主程序

        mov esi,offset aWalk                          ; 将aWalk 的偏移地址赋值到esi中

        call TakeDrunkenWalk                        ; 调用本逻辑的主要函数TakeDrunkenWalk,让“醉汉”走起来

        exit

main ENDP

 

 

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

TakeDrunkenWalk PROC

LOCAL currX:WORD,currY:WORD

;

; Take a walk in random direction (north ,south,east,west).         ;记得调用之前吧aWalk赋给了ESI吗?本函数接收esi为参数

; Receives : ESI points to a DrunkardWalk structure

; Returns : the structure is initialized with random values

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

          pushad                                                                                ; 将所有寄存器压入堆栈

; Point EDI to the array of  COORD objects.

          mov edi,esi                                                                          ; 将ESI赋到edi中

          add edi,OFFSET DrunkardWalk.path                                    ; 计算出了aWalk结构中的path成员地址

          mov ecx,WalkMax                 ; loop count                            ; 最多能走的步数赋到ecx中

          mov currX,StartX                   ; current X-location                 ; 开始X坐标赋到currX中

          mov currY,StartY                    ; current Y-location                ; 开始Y坐标赋到currY中

 

Again:

          ; insert current location in array

          mov ax,currX                                       ; 将currX保存到ax中

          mov (COORD PTR [edi]).X , ax             ; 将ax赋到aWalk结构中的path成员的X成员,因为是间接引用,所以这里使用了PTR

          mov ax,currY

          mov (COORD PTR [edi]).Y , ax

 

          INVOKE DisplayPosition , currX , currY              ; 调用DisplayPosition 打印目前的XY坐标

          mov eax,4            ; choose a direction (0-3)    ; 将4赋值到eax中,用来生成随机数,范围为0-3

          call RandomRange                                            ; 生成随机数,仍然保存在eax中

          

          .IF eax==0                    ; north                         ; 判断生成的随机数到底是哪个方向,然后分情况进行相应计算

          inc currY

          .ELSEIF eax==1            ; south

          dec currY

          .ELSEIF eax==2            ; west

          dec currX

          .ELSE                            ; east (eax = 3)

           inc currX

          .ENDIF

 

          add edi,TYPE COORD    ; 指向path成员的下一个坐标地址

          loop Again                    ; 接着走醉步

 

Finish:

          mov (DrunkardWalk PTR [esi]).pathsUsed,WalkMax    ; 不知道这里要为什么要赋回去

          popad

          ret

TakeDrunkenWalk ENDP

 

 

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

DisplayPosition PROC currX:WORD,currY:WORD                           

; 用来将X,Y坐标输出的函数,接收X,Y坐标作为参数

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

.data

commaStr BYTE ",",0

.code

           pushad

           movzx eax,currX                          ; current X postion

           call WriteDec

           mov edx, OFFSET commaStr        ; "," string

           call WriteString

           movzx eax,currY                          ; current Y position

           call WriteDec

           call Crlf

           popad

           ret

DisplayPosition ENDP

END main

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息