# Experiment 2 compilation and debugging of assembly source program of multiple logic segments

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

data segment
db 16 dup(0)
data ends

stack segment
db 16 dup(0)
stack ends
code segment
start:
mov ax, data
mov ds, ax

mov ax, stack
mov ss, ax
mov sp, 16

mov ah, 4ch
int 21h
code ends
end start```

(2)task1_1. Screenshot after debugging to the end of line17 and before line19:

Answer: ① at this time, register DS=076A, SS=076B, CS=076C;

② Assuming that after the program is loaded, the segment address of the code segment is X, the segment address of the data segment is X-2h, and the segment address of the stack is X-1h.

Reason: 16B memory is reserved for both data segment and stack segment, and memory address = segment address * 16 + offset address, so the address difference between adjacent segments is 1h

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

data segment
db 4 dup(0)
data ends

stack segment
db 8 dup(0)
stack ends
code segment
start:
mov ax, data
mov ds, ax

mov ax, stack
mov ss, ax
mov sp, 8

mov ah, 4ch
int 21h
code ends
end start```

task1_2. Screenshot of observing the values of registers DS, CS and SS at the end of debugging to line17 and before line19:

① At this time, register DS=076A, SS=076B, CS=076C;

② Assuming that after the program is loaded, the segment address of the code segment is X, the segment address of the data segment is X-2h, and the segment address of the stack is X-1h.

Reason: the memory allocated by the system is in 16B units, and the allocated memory is 16 multiples. If it is insufficient, it will be made up. Therefore, 16B space is reserved for the data segment and stack segment of this program; The difference between adjacent segment addresses is 1h.

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

data segment
db 20 dup(0)
data ends

stack segment
db 20 dup(0)
stack ends
code segment
start:
mov ax, data
mov ds, ax

mov ax, stack
mov ss, ax
mov sp, 20

mov ah, 4ch
int 21h
code ends
end start```

task1_3. Screenshot of observing the values of registers DS, CS and SS at the end of debugging to line17 and before line19:

① At this time, register DS=076A, SS=076C, CS=076E;

② Assuming that after the program is loaded, the segment address of the code segment is X, the segment address of the data segment is X-4h, and the segment address of the stack is X-2h.

Reason: the allocated segment memory is 16 times, so 32B space is reserved for the data segment and stack segment of this program; The difference between adjacent segment addresses is 2h.

```assume ds:data, cs:code, ss:stack
code segment
start:
mov ax, data
mov ds, ax

mov ax, stack
mov ss, ax
mov sp, 20

mov ah, 4ch
int 21h
code ends

data segment
db 20 dup(0)
data ends

stack segment
db 20 dup(0)
stack ends
end start```

task1_4. Screenshot of observing the values of registers DS, CS and SS at the end of debugging to line17 and before line19:

① At this time, register DS=076C, SS=076E, CS=076A;

② Assuming that after the program is loaded, the segment address of the code segment is X, the segment address of the data segment is X+2h, and the segment address of the stack is X+4h.

Reason: the address order between segments is allocated according to the compilation order.

① The amount of memory space actually allocated to this segment is   (ceil)(N/16)*16   (ceil is rounded up)

②   Only task1_4.asm can still be executed correctly. end start informs the compiler that the entry of the program is at start. Removing start may lead to an error in the location of the CS segment address. task1_4. The sequence of the middle section is CS, DS and SS. After removing start, the beginning of the program area pointed to by CS: IP is also a code segment, so the program can be executed correctly.

Operation method of assembler:

1. Find a free memory area with sufficient capacity with a starting address of SA: 0000 (i.e. the offset address of the starting address is 0).
2. In the first 256 bytes of this memory area, a data area called program segment prefix (PSP) is created. DOS uses PSP to communicate with the loaded program.
3. Start from 256 bytes of this memory area (after PSP), load the program, and the address of the program is set to SA+10H:0; The free memory area starts from SA: 0, 0 ~ 255 bytes are PSP, and the program is stored from 256 bytes. In order to better distinguish PSP and program, DOS will be divided into different segments, as follows:
Free memory area: SA: 0
PSP area: SA: 0
Program area: SA+10H: 0
Note: Although the physical addresses of PSP area and program area are continuous, they have different segment addresses.
4. Store the segment address (SA) of the memory area in DS, initialize other relevant registers, and set CS: IP to point to the entry of the program (SA+10H: 0).

1. For ds, when the program is loaded, the ds segment address points to the PSP address. To point to the data segment, you need to assign values in the program;

2. For cs, the segment address is determined by the start specified by end start; If there is no start, cs: ip points to (SA+10H: 0).

Assembly source code:

```assume cs:code
code segment
start:mov ax,0b800h
mov ds,ax
mov bx,0f00h
mov cx,80
mov dx,0403h
s:mov ds:[bx],dx
loop s

mov ah,4ch
int 21h
code ends
end start```

Before running the program:

After the program runs

Source code:

```assume cs:code
data1 segment
db 50, 48, 50, 50, 0, 48, 49, 0, 48, 49 ; ten numbers
data1 ends

data2 segment
db 0, 0, 0, 0, 47, 0, 0, 47, 0, 0       ; ten numbers
data2 ends

data3 segment
db 16 dup(0)
data3 ends

code segment
start:
mov bx, 0       ;Offset address of corresponding position
mov ax, data1
mov ds, ax
mov cx, 0ah
s:  mov ax, [bx]
add ax, [bx+10h]    ;data1 and data2 Data addition of
mov [bx+20h], ax    ;put to data3 In paragraph
inc bx
loop s

mov ah, 4ch
int 21h
code ends
end start```

Disassembly:

Before operation:

After operation:

The three lines are data1, data2 and data3 respectively. It can be seen that data1 and data2 at the corresponding position are added and stored in data3.

Source code:

```assume cs:code

data1 segment
dw 2, 0, 4, 9, 2, 0, 1, 9
data1 ends

data2 segment
dw 8 dup(?)
data2 ends

code segment
start:
mov ax, data1
mov ds, ax
mov ax, data1+02h
mov ss, ax      ;take data2 Used as stack segment
mov sp, 20h     ;The top of the stack points to the high address
mov cx, 8
mov bx, 0
s:  push [bx]
loop s

mov ah, 4ch
int 21h
code ends
end start```

Disassembly:

Before operation:

After operation:

The two lines are segments data1 and data2 respectively. You can see that the contents of data1 have been stored in data2 in reverse order; At the same time, it is noted that the value at 076A:0b~076A:0f in data1 changes because the program is interrupted and the FALG, CS and IP at this time are stored in the stack space

Source code:

```assume cs:code, ds:data
data segment
db 'Nuist'
db 2, 3, 4, 5, 6
data ends

code segment
start:
mov ax, data
mov ds, ax

mov ax, 0b800H
mov es, ax

mov cx, 5
mov si, 0
mov di, 0f00h
s:      mov al, [si]
and al, 0dfh
mov es:[di], al
mov al, [5+si]
mov es:[di+1], al
inc si
loop s

mov ah, 4ch
int 21h
code ends
end start```

Operation results:

The function of line19: convert 0dfh into binary to 1101 1111, and its bitwise and subsequent third bit becomes 0, and other bits remain unchanged; According to the ASCII code table, the difference between upper and lower case letters lies in the third bit, so changing the third bit to 0 is to convert lower case letters into upper case letters (upper case letters remain the same).

Operation results after modifying line4 to db 5 dup(2):

Result after modification to db 5 dup(5):

Source code:

```assume cs:code, ds:data

data segment
db 'Pink Floyd      '
db 'JOAN Baez       '
db 'NEIL Young      '
db 'Joan Lennon     '
data ends

code segment
start:
mov ax, data
mov ds, ax
mov bx, 0       ;Row offset address
mov cx, 4       ;Four lines
mov si, 0       ;Letter pointer in word
s1:     ;Enter outer circulation
mov di, cx      ;Save the number of cycles
mov cx, 4       ;The first word in each line is 4 letters, so the number of memory cycles is 4
s2:     ;Enter inner circulation
mov al, [bx+si]     ;Take out the letters one by one
or al, 20h          ;And 20 h Bitwise or convert to lowercase
mov [bx+si], al     ;Return to the original position
inc si              ;Next letter
loop s2             ;End of inner loop

add bx, 10h         ;Go to the next line
mov si, 0           ;Letter pointer reset
mov cx, di          ;Recovery cycle test times
loop s1             ;End of outer cycle

mov ah, 4ch
int 21h
code ends
end start```

Disassembly:

Operation results:

You can see that the first word of each line in the data segment is converted to lowercase.

Source code:

```assume cs:code, ds:data, es:table

data segment
db '1975', '1976', '1977', '1978', '1979'
dd  16, 22, 382, 1356, 2390
dw  3, 7, 9, 13, 28
data ends

table segment
db 5 dup( 16 dup(' ') )  ;
table ends

code segment
start:
mov ax, data
mov ds, ax
mov ax, table
mov es, ax      ;target table address
mov bx, 0       ;table Row address of
mov si, 0       ;data Data pointer in segment
mov cx, 5       ;Write 5 lines at a time
mov di, 0       ;table Pointer in each line in
;Write year
year:   ;Outer loop, write one line at a time
mov ax, cx      ;Number of save cycles
mov cx, 4       ;The year of each line accounts for 4 bytes, and it takes 4 times to write by byte
year1:  ;Inner loop, write one byte, that is, one number at a time
mov dl, ds:[si]     ;Memory cells cannot be moved directly. Borrow dl Take by word
mov es:[bx+di], dl
inc si          ;data The data in is continuous, so it is taken by word+1
inc di          ;Year in table The offset address of each row in the is 0~3
loop year1
add bx, 10h     ;Go to the next line
mov di, 0       ;di Return to initial position
mov cx, ax      ;Number of recovery cycles
loop year

;Write revenue
mov cx, 5
mov bx, 0
mov di, 5
income:
mov ax, cx
mov cx, 2       ;The income is stored as double words, but only single words can be taken at a time, and 2 cycles are required for each line
income1:
mov dx, ds:[si]     ;Take by word
mov es:[bx+di], dx
add si, 2       ;Move 2 bytes per word
loop income1
add bx, 10h     ;next row
mov di, 5       ;Return to the initial position written in each line
mov cx, ax
loop income

;Write employee
mov cx, 5
mov bx, 0
mov di, 0ah
employee:
mov dx, ds:[si]     ;Take by word
mov es:[bx+di], dx
loop employee

;Write in per capita income
mov cx, 5
mov bx, 0
mov di, 0dh
avgincome:
mov dx, es:[bx+7]       ;The divisor is a double word, that is, 32 bits dx 16 bits high, ax Save low 16 bits
mov ax, es:[bx+5]
div word ptr es:[bx+0ah]    ;The divisor is 16 bits and the quotient exists ax In, the remainder exists dx in
mov es:[bx+di], ax
loop avgincome

mov ah, 4ch
int 21h
code ends
end start```

View the screenshot of the original data information of the table segment:

Screenshot after operation:

You can see that the data in the data segment has been saved in the table segment according to the structure, and the calculation result of per capita income is correct.

Posted by jnutter on Sun, 07 Nov 2021 18:18:11 -0800