Experiment Task 1
This task is to help us understand the flexible use of operator offset, pseudo-directive equ, predefined symbol $
After disassembly, you know that offset followed by offset address has been positioned after the program has loaded. equ means equal. Predefined symbol $does not occupy code memory.
assume cs:code, ds:data data segment x db 1, 9, 3 len1 equ $ - x y dw 1, 9, 3 len2 equ $ - y data ends code segment start: mov ax, data mov ds, ax mov si, offset x mov cx, len1 mov ah, 2 s1:mov dl, [si] or dl, 30h;Convert to corresponding ASCII code int 21h mov dl, ' ' int 21h inc si loop s1 mov ah, 2 mov dl, 0ah int 21h mov si, offset y mov cx, len2/2 mov ah, 2 s2:mov dx, [si] or dl, 30h int 21h mov dl, ' ' int 21h add si, 2 loop s2 mov ah, 4ch int 21h code ends end start
Post-run screenshots:
Question answering:
(1) line27, the assembly instruction loop s1 jumps according to the amount of displacement. Through debug disassembly, we can see that the machine code is E2F2, where E2 corresponds to Loop's machine code, then we can judge that F2 is his displacement. Through the knowledge learned in the course and consulting related data, F2 is stored in the form of complement, converting it to binary is 1000 1110, that is, decimal-14.
From the CPU point of view, first look at the offset address after the loop is 000D, and then look at the start address of the next instruction is 001B, then from 000D-001B=-000E, the conversion to decimal is -14.
Deug disassembly screenshot:
(2) line44, the assembly instruction loop s2 jumps according to the amount of displacement. The process of analysis is similar to that described above, where the answer is given directly, with an offset of 16, obtained from 0029h-0039h. It also satisfies this answer by looking at F0 in the machine code.
Experiment Task 2
The purpose of this task is to understand the principles of call directives.
Click to view the codeassume cs:code, ds:data data segment dw 200h, 0h, 230h, 0h data ends stack segment db 16 dup(0) stack ends code segment start: mov ax, data mov ds, ax mov word ptr ds:[0], offset s1 mov word ptr ds:[2], offset s2 mov ds:[4], cs mov ax, stack mov ss, ax mov sp, 16 call word ptr ds:[0] s1: pop ax call dword ptr ds:[2] s2: pop bx pop cx mov ah, 4ch int 21h code ends end start(1) According to the jump principle of call instruction, the contents of three registers are obtained by theoretical analysis.
When this command is executed, there are two call directives in the source code. We analyze them one by one. First, we look at the first call, where the call directive goes to S1 and pushes the stack memory size of word, that is, the IP of S1 into the stack. Correspondingly, at the second call instruction, the memory size pushed into the stack is dword, so the second call instruction pushes the C s and IP of S2 into the stack in turn. All pop instructions that follow S1 and S2 are not difficult to obtain, ax=s1 ip, bx=s2 ip, cx=s2 C s. The corresponding content is shown in the following screenshot:
The theoretical analysis is completed and the debug results are as follows:
Compliance with the results of the analysis!
Experiment Task 3
The requirement is that the data in the data segment be output in decimal. The logical segment is as follows:
data segment x db 99, 72, 85, 63, 89, 97, 55 len equ $- x data ends
In addition, the command to output a single character is:
mov ah, 2 mov dl, ×× ; ××Is the character to be output, or ASCⅡCode value int 21h
As you can see, these arrays are two digits. When you try to output them directly, you will find that all the memory units stored in them are hexadecimal, which does not satisfy the theme. The relevant screenshots are lost and you can make up your own brain based on this memory.
Then this topic is to separate these two digits, in order to convert each character into ASCII code output, the relevant code is as follows:
assume cs:code, ds:data data segment x db 99, 72, 85, 63, 89, 97, 55 len equ $- x data ends code segment start: mov ax, data mov ds, ax mov si, offset x mov cx, len s: call printNumber call printSpace loop s mov ah, 4ch int 21h printNumber: mov ah, 0 mov al, [si] mov bl, 10 div bl mov bx, ax mov ah, 2 mov dl, bl or dl, 30h int 21h mov dl, bh or dl, 30h int 21h inc si ret printSpace: mov ah, 2 mov dl, ' ' int 21h ret code ends end startThe main study is the application of the `div` command and the conversion of characters to ASCII codes. The following screenshots are taken after running:
In addition, it is worth considering whether there is a way to convert these numbers into strings so that they can be output regardless of the number of words. This is also the blogger's initial idea to solve the problem, but the process of implementation is a bit complex, after consulting some of the data, the method is converted. I hope I can master relevant methods after further study.
Experiment Task 4
Output the following data segments on the screen as required
data segment str db 'try' len equ $ - str data ends
Requires that this character be output in green and red in the upper left corner and the lower left corner, respectively.
Analysis: First of all, you can write related subroutines according to your requirements. The entry parameters are the address at the beginning of the string, the length of the string, the length of the string, the color of the string, and the specified line.
Let's work it out one by one. The first address of the string can be offset to store str in the si register. The length of the string is very simple. By definition, it is the size of the len. The specified line can be known by the range, the first line bh=0, the last line bh=24. Finally, determine its color, as you learned from the book:
Then the green characters on the black background should be 00000010b, which is 2 in the decimal system, and the red on the black background is 00000100b, which is 4 in the decimal system.
The remaining question is how to locate it, as shown in the following code:
assume cs:code, ds:data data segment str db 'try' len equ $ - str data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800h mov es, ax;Display memory location mov cx, len mov si, offset str mov bh, 0 mov bl, 2 call printStr mov cx, len mov si, offset str mov bh, 24 mov bl, 4 call printStr mov ah, 4ch int 21h ; subroutine: printStr ; function: Display string on screen at specified line, with specified color ; Entry parameters: ; Address of first character in string --> ds:si (Where the segment address of the string is -> ds, Offset Address for String Start Address -> si) ; String Length --> cx ; String color --> bl ; Specify Row --> bh (Value:0 ~ 24) printStr: mov al, bh;Calculate starting address in di in mov dl, 0a0h mul dl mov di, ax mov ah, bl s: mov al, [si] mov es:[di], ax add di, 2 inc si loop s ret code ends end start
As you can see from the code, this is a direct calculation of the address of the corresponding line, using the mul directive. There are 25 known lines with 80 characters per line. The output is in the form of corresponding characters + attributes. All attributes are stored in ah, all in al, and ax in the corresponding display location.
The results are as follows:
In accordance with the intention of the title, the main research is to make a reasonable use of various addresses, and how to write a program when the title has some data requirements.
Experiment Task 5
At 80 × In 25 color character mode, the school number is displayed in the middle of the last line of the screen. Require output window blue bottom, school number and polylines on both sides to
White foreground color display.
The logical segment is:
data segment stu_no db '201983290487' len = $ - stu_no data ends
This topic divides the task into two parts. First, set the whole page to white on blue background, and then output the required format on the last line. The code is as follows:
assume cs:code, ds:data data segment stu_no db '201983290487' len = $ - stu_no data ends code segment start: mov ax, data mov ds, ax mov ax, 0b800h mov es, ax mov bh, 0 mov al, bh;Calculate starting address in di in mov dl, 0a0h mul dl mov di, ax mov ax, 24;Calculate how many times you need to repeat to turn the screen into white on blue mov dl, 80 mul dl mov cx, ax s1: mov al, ' ' mov ah, 17h;White on Blue mov es:[di], ax add di, 2 loop s1 mov si, offset stu_no mov bh, 24 mov al, bh;Calculate starting address in di in mov dl, 0a0h mul dl mov di, ax call printStr mov ax, 4c00h int 21h printStr: call printline mov cx, len s2: mov ah, 17h;White on Blue mov al, [si] mov es:[di], ax inc si add di, 2 loop s2 call printline ret printline: mov cx, 34;(80-12)/2 s3: mov ah, 17h mov al, '-' mov es:[di], ax add di, 2 loop s3 ret code ends end start
This topic has something in common with experimental task 4, but on the basis of task 4, the calculation of subroutine calls and number of program executions has been improved.
The results are as follows:
Meet the requirements!
Experimental summary
This experiment already has requirements for some relatively practical tasks and is getting closer to the actual programming. There are also gains and reflections in writing some topics. When I was working on Experiment 3, my first thought was to output these data directly, find the corresponding content of the 16-digit ASCII code of the output, and I was thinking about whether I could convert these numbers directly into strings, which would also be easy to output, but when I read the relevant data, I also learned the complexity. It deviates from the requirements of this task, but in the future, I hope to master these methods gradually.
As the experiment goes deeper and deeper, we are not satisfied with the use of commands or the judgment of addresses or the use of registers. On this basis, we try to achieve some complex tasks and apply the knowledge we have learned to practice. We will inevitably encounter some difficulties in the process. However, communicating with your classmates or consulting the data is the solution. Solving problems one after another is a reward.