《彙編語言》王爽—實驗五詳解

由於我自己的沒法複製,並且不帶的更改了,所以可能會和其他人有些答案重合,但確保正確。

(1)將下面的程序編譯連接,用Debug加載、跟蹤,然後回答問題。

assume cs:code,ds:data,ss:stack 

data segment 

        dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h 

data ends 

stack segment 

        dw 0,0,0,0,0,0,0,0 

stack ends 

code segment 

start:  mov ax,stack 

        mov ss,ax 

        mov sp,16 

        mov ax,data 

        mov ds,ax 

        push ds:[0] 

        push ds:[2] 

        pop ds:[2] 

        pop ds:[0] 

        mov ax,4c00h 

        int 21h 

code ends 

end start 

①CPU執行程序,程序返回前,data段中的數據 不變 。

②CPU執行程序,程序返回前,CS= 0C88H ,SS= 0C87H ,DS= 0C86H 。

③設程序加載後,CODE段的段地址爲X,則DATA段的段地址爲 X-2 ,STACK段的段地址爲 X-1 。

C:\DOCUME~1\ADMINI~1>debug sy5-1.exe

-r

AX=0000  BX=0000  CX=0042  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=0C76  ES=0C76  SS=0C86  CS=0C88  IP=0000   NV UP EI PL NZ NA PO NC

0C88:0000 B8870C        MOV     AX,0C87

-d 0c86:0 f

0C86:0000  23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09   #.V.............

-u

0C88:0000 B8870C        MOV     AX,0C87

0C88:0003 8ED0          MOV     SS,AX

0C88:0005 BC1000        MOV     SP,0010

0C88:0008 B8860C        MOV     AX,0C86

0C88:000B 8ED8          MOV     DS,AX

0C88:000D FF360000      PUSH    [0000]

0C88:0011 FF360200      PUSH    [0002]

0C88:0015 8F060200      POP     [0002]

0C88:0019 8F060000      POP     [0000]

0C88:001D B8004C        MOV     AX,4C00

-g 001d

AX=0C86  BX=0000  CX=0042  DX=0000  SP=0010  BP=0000  SI=0000  DI=0000

DS=0C86  ES=0C76  SS=0C87  CS=0C88  IP=001D   NV UP EI PL NZ NA PO NC

0C88:001D B8004C        MOV     AX,4C00

-d 0c86:0 f

0C86:0000  23 01 56 04 89 07 BC 0A-EF 0D ED 0F BA 0C 87 09   #.V.............

-q

(2)將下面的程序編譯連接,用Debug加載、跟蹤,然後回答問題。

assume cs:code,ds:data,ss:stack 

data segment 

        dw 0123h,0456h

data ends 

stack segment 

        dw 0,0

stack ends 

code segment 

start:  mov ax,stack 

        mov ss,ax 

        mov sp,16 

        mov ax,data 

        mov ds,ax 

        push ds:[0] 

        push ds:[2] 

        pop ds:[2] 

        pop ds:[0] 

        mov ax,4c00h 

        int 21h 

code ends 

end start 

①CPU執行程序,程序返回前,data段中的數據 不變 。

②CPU執行程序,程序返回前,CS= 0C88H ,SS= 0C87H ,DS= 0C86H 。

③設程序加載後,CODE段的段地址爲X,則DATA段的段地址爲 X-2 ,STACK段的段地址爲 X-1 。

④對於如下定義的段:

name segment

……

name ends

如果段中的數據佔N個字節,則程序加載後,該段實際佔有的空間爲 ((N+15)/16)*16 。

④解析:

N分爲被16整除和不被16整除。

當N被16整除時: 佔有的空間爲(N/16)*16

當N不被16整除時: 佔有的空間爲(N/16+1)*16,N/16得出的是可以整除的部分,還有一個餘數,餘數肯定小於16,加上一個16。

程序加載後分配空間是以16個字節爲單位的,也就是說如果不足16個字節的也分配16個字節。

兩種情況總結成一個通用的公式:((N+15)/16)*16

C:\DOCUME~1\ADMINI~1>debug sy5-2.exe

-r

AX=0000  BX=0000  CX=0042  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=0C76  ES=0C76  SS=0C86  CS=0C88  IP=0000   NV UP EI PL NZ NA PO NC

0C88:0000 B8870C        MOV     AX,0C87

-d 0c86:0 3

0C86:0000  23 01 56 04                                       #.V.

-u

0C88:0000 B8870C        MOV     AX,0C87

0C88:0003 8ED0          MOV     SS,AX

0C88:0005 BC1000        MOV     SP,0010

0C88:0008 B8860C        MOV     AX,0C86

0C88:000B 8ED8          MOV     DS,AX

0C88:000D FF360000      PUSH    [0000]

0C88:0011 FF360200      PUSH    [0002]

0C88:0015 8F060200      POP     [0002]

0C88:0019 8F060000      POP     [0000]

0C88:001D B8004C        MOV     AX,4C00

-g 001d

AX=0C86  BX=0000  CX=0042  DX=0000  SP=0010  BP=0000  SI=0000  DI=0000

DS=0C86  ES=0C76  SS=0C87  CS=0C88  IP=001D   NV UP EI PL NZ NA PO NC

0C88:001D B8004C        MOV     AX,4C00

-d 0c86:0 3

0C86:0000  23 01 56 04                                       #.V.

-q

(3)將下面的程序編譯連接,用Debug加載、跟蹤,然後回答問題。

assume cs:code,ds:data,ss:stack 

code segment 

start:  mov ax,stack 

        mov ss,ax 

        mov sp,16 

        mov ax,data 

        mov ds,ax 

        push ds:[0] 

        push ds:[2] 

        pop ds:[2] 

        pop ds:[0] 

        mov ax,4c00h 

        int 21h 

code ends 

data segment 

        dw 0123h,0456h

data ends 

stack segment 

        dw 0,0

stack ends 

end start 

①CPU執行程序,程序返回前,data段中的數據 不變 。

②CPU執行程序,程序返回前,CS= 0C86H ,SS= 0C8AH ,DS= 0C89H 。

③設程序加載後,CODE段的段地址爲X,則DATA段的段地址爲 X+3 ,STACK段的段地址爲 X+4 。

C:\DOCUME~1\ADMINI~1>debug sj5-3.exe

-r

AX=0000  BX=0000  CX=0044  DX=0000  SP=0000  BP=0000  SI=0000  DI=0000

DS=0C76  ES=0C76  SS=0C86  CS=0C86  IP=0000   NV UP EI PL NZ NA PO NC

0C86:0000 B88A0C        MOV     AX,0C8A

-u

0C86:0000 B88A0C        MOV     AX,0C8A

0C86:0003 8ED0          MOV     SS,AX

0C86:0005 BC1000        MOV     SP,0010

0C86:0008 B8890C        MOV     AX,0C89

0C86:000B 8ED8          MOV     DS,AX

0C86:000D FF360000      PUSH    [0000]

0C86:0011 FF360200      PUSH    [0002]

0C86:0015 8F060200      POP     [0002]

0C86:0019 8F060000      POP     [0000]

0C86:001D B8004C        MOV     AX,4C00

-g 001d

AX=0C89  BX=0000  CX=0044  DX=0000  SP=0010  BP=0000  SI=0000  DI=0000

DS=0C89  ES=0C76  SS=0C8A  CS=0C86  IP=001D   NV UP EI PL NZ NA PO NC

0C86:001D B8004C        MOV     AX,4C00

-d 0c89:0 3

0C89:0000  23 01 56 04                                       #.V.

-q

(4)如果將(1)、(2)、(3)題中的最後一條僞指令“end start”改爲“end”(也就是說,不指明程序的入口),則哪個程序仍然可以正確執行?請說明原因。

答:第三條程序仍然可以正確執行,如果不指明入口位置,則程序從所分配的空間開始執行,前2個是數據段,只有從第3條開始是指令代碼。

5)程序如下,編寫code段中代碼,將a段和b段中的數據依次相加,將結果存到C段中。

方法一:兩次循環

assume cs:code

a segment

    db 1,2,3,4,5,6,7,8

a ends

b segment

    db 1,2,3,4,5,6,7,8

b ends

c segment

    db 0,0,0,0,0,0,0,0

c ends

code segment

start: mov ax,a

       mov ds,ax

       mov ax,b

       mov es,ax

       mov bx,0

       mov cx,8

    s: mov al,[bx]

       add es:[bx],al

       inc bx

       loop s

       mov ax,c

       mov ds,ax

       mov bx,0

       mov cx,8

   s0: mov al,es:[bx]

       mov [bx],al

       inc bx

       loop s0

    mov ax,4c00h

    int 21h

code ends

end start

方法二:一次循環

assume cs:code

a segment

    db 1,2,3,4,5,6,7,8

a ends

b segment

    db 1,2,3,4,5,6,7,8

b ends

c segment

    db 0,0,0,0,0,0,0,0

c ends

code segment

start: mov ax,a

       mov ds,ax   ;ds指向a段地址

       mov ax,b

       mov es,ax   ;es指向b段地址

       mov bx,0

       mov cx,8

    s: mov al,[bx]

       add al,es:[bx]

       mov dx,c

       mov ds,dx   ;ds指向c段地址

       mov [bx],al

       mov ax,a

       mov ds,ax   ;重新將ds指向a段(好像此處還能改進)

       inc bx

       loop s

    mov ax,4c00h

    int 21h

code ends

end start

方法三:程序二的改進版

assume cs:code 

a segment 

        db 1,2,3,4,5,6,7,8 

a ends 

b segment 

        db 1,2,3,4,5,6,7,8 

b ends 

c segment 

        db 0,0,0,0,0,0,0,0 

c ends 

code segment 

start: 

        mov ax,a 

        mov ds,ax 

        mov ax,b 

        mov es,ax 

        mov ax,c 

        mov ss,ax 

        mov bx,0 

        mov cx,8 

s:      mov ax,[bx] 

        mov ss:[bx],ax 

        mov ax,es:[bx] 

        add ss:[bx],ax 

        inc bx 

        loop s

        mov ax,4c00h 

        int 21h 

code ends 

end start

(6)程序如下,編寫code段中代碼,用PUSH指令將A段中的前8個字型數據,逆序存儲到B段中。

assume cs:code

a segment

    dw 1,2,3,4,5,6,7,8

a ends

b segment

    dw 0,0,0,0,0,0,0,0

b ends

code segment

start: mov ax,a

       mov ds,ax   ;ds指向a段

       mov ax,b

       mov bx,0    ;ds:bx指向a段的第1個單元

       mov ss,ax

       mov sp,16   ;設置棧頂指向b:16

       mov cx,8

    s: push [bx]

       add bx,2

       loop s      ;將a段中0~16個單元逆次入棧

code ends

end start

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章