It took me more than half a month to complete the assembly language of Teacher Wang Shuang, follow CMU’s video class + textbook, and learn the knowledge of the third chapter. My deepest feeling is that CSAPP’s quality is very hard, both in video and book, worthy of its reputation. (Lab6 and the homework after class have not been done yet, I will make up later) Now let’s make a summary of what we have learned. (Roughly in the order of CMU videos)

1. Basics

1. Use instructions to create, edit, assemble, link assembly language program ① Create and edit source code command: getdit sum.c Description: Gedit is a GNOME desktop environment compatible with UTF-8 text editor. You can also create and edit using vi or Vim. C -> sum. I: GCC -e sum.c -o sum. I: sum.c -> sum. I: GCC -e sum.c -o sum. Sum.s -> sum.o = sum.s -o sum.o = sum.s -o sum.o = sum.s -o sum.o = sum.s -o sum.o = sum.s -o sum.o O -o sum = sum.o -o sum = sum.o -o sum = sum.o -o sum = sum.o -o sum = sum.o -o sum The linking process connects related object files to each other so that all object files become a unified whole that can be executed. ⑥ Run the./sum command. Note: The executable file is executed

2. Data format B (byte) : byte W (word) : 1 word =2 bytes L (double words) : double words =4 bytes q (quad words) : four words =8 bytes The corresponding MOV instruction is movb movW movL MOVq

Al: 1 byte AX: 2 bytes EAX: 4 bytes RAx: 8 bytes

3. Data transmission Format of memory data:Format of transmission address: Extension:Extension is divided into zero extension and sign extension. To keep the same number after extension, for signed number, sign extension (that is, high-order complement of the original highest bit) can guarantee the same before and after extension; for unsigned number, zero extension can guarantee the same before and after extension. Instruction, for example byte -> word, others in the same format. Zero extension: MOVZBW DL, AX symbol extension: MOVSBW DL, AX other, symbol extension one more CLTQ instruction, means %(EAX) symbol extension -> RAx other, when assigned to the 32-bit register, always automatically change the high to 0

4. Register function

0-63. 0-31 0-15 8-15 0 to 7 Use practices
%rax %eax %ax %ah %al Save return value
%rbx %ebx %bx %bh %bl Saved by the caller
%rcx %ecx %cx %ch %cl The fourth parameter
%rdx %edx %dx %dh %dl The third parameter
%rsi %esi %si There is no %sil The second parameter
%rdi %edi %di There is no %dil The first parameter
%rbp %ebp %bp There is no %bpl Saved by the caller
%rsp %esp %sp There is no %spl The stack pointer
%r8 %r8d %r8w There is no %r8b The fifth parameter
%r9 %r9d %r9w There is no %r9b The sixth parameter
%r10 %r10d %r10w There is no %r10b Caller save
%r11 %r11d %r11w There is no %r11b Caller save
%r12 %r12d %r12w There is no %r12b Saved by the caller
%r13 %r13d %r13w There is no %r13b Saved by the caller
%r14 %r14d %r14w There is no %r14b Saved by the caller
%r15 %r15d %r15w There is no %r15b Saved by the caller
The first six parameters exist rdi rsi rdx rcx r8 r9If there are more parameters, put on the stack, and the top of the stack is the 7th parameter, the next is the 8th parameter…
rbx rdx r12~r15If you want to call another function in the function body, you can put useful data in the registers saved by the caller. In this way, if you want to change the value of these registers in the called function, it will always be pushed and popped before return.
Registers saved by the caller are always stored on the stack before the function is called, and useful data that is not expected to be modified is popped for use after the function is called.

5. Arithmetic and logical operations Note the arithmetic right shift (SAR) and the logical right shift (SHR). The arithmetic right shift is the right shift of signed numbers, with the high complement of 1, and the logical right shift is the right shift of unsigned numbers, with the high complement of 0.

Imulq: signed full multiplication mulq: unsigned full multiplication idivq: Signed division product % RDX (high 64 bits) and %rax (low 64 bits) quotient %rax, remainder % RDX.

Question: Why does the imulq instruction product in homework 1 exist in RDX... ??

Control Control

1.Condition Code Indicates the Condition code

Condition code English meaning
CF Carry Flag (for unsigned) The carry mark for adding unsigned numbers
ZF Zero Flag The result is 0
SF Sign Flag (for signed) , the most significant bit of the operation result is 1 (negative), then SF is set to 1
OF Overflow Flag (for signed) Overflow flag, which represents an overflow of signed numbers (if two signed numbers add up to different symbols, this overflow occurs)
Lea does not set these four flag bits.
CMPQ is used to compare sizes, and testq is used to compare a number to 0

CF and OF difference :(reference to the big guy’s blog) first OF all need to know, the computer to the value OF the storage OF the form OF complementary storage, one to avoid the embarrassment OF +0 and -0, the number OF addition and subtraction can be unified as the addition OF complement. At the assembly language level, when defining variables, there is no signed and unsignde, the assembler will all you input integer literals as signed numbers (the highest sign bit according to the input numeric symbol is determined by the binary complement code stored in the computer, only this standard! The assembler doesn’t distinguish between signed and unsigned and treats it with both standards, it’s both signed! And it all assembles into complement!


② Then, how do computers distinguish between signed and unsigned numbers and adopt different strategies for their operations? An important point is that the complement is a powerful design that allows the addition of unsigned and signed numbers to be the same, adding them one by one from zero to the highest order, and adding the carry as you do so. So, unsigned number and signed number in addition operations do not distinguish, with the same adder can, but the results have different interpretation power.


③ OF, CF, SF logo. Let’s start with the CF bit. The book says that the CF bit is only meaningful for unsigned numbers. One thing to understand is that even if you add two signed numbers, it will change the CF bit. The change of the flag bit of CF is caused by the carrying or borrowing of the most significant bit (the 8th bit if it is 8 bits) to the higher bit (the 9th bit). For signed numbers, the change of the highest bit is the sign bit, and the change of its meaning is different from the change of the value bit. So for signed numbers, CF might change, but it doesn’t change meaningfully. If it is an unsigned number, its change means that the 8 bits of memory or registers in it are not enough to hold the data because the data is carried or borrowed. Look OF flags, it only to have symbols for meaningful, because the two standard 8-bit signed data (don’t assign standard refers to the assignment more than a signed number range OF Numbers, because OF the truncation, which is eight potential energy save, save the data in numerical size have changed), the two data only with Numbers (positive or negative) additive will overflow, That is, the result is beyond the range of signed numbers. For example, two positive numbers, the sign bit (the 8th bit) is 0, after adding, overflow happens, the sign bit becomes 1 due to the carry of the 7th bit, the two positive numbers add to become negative, right? In this way, the effect OF OF is due to the change OF the sign bit. If there are two unsigned numbers, the highest bit does not represent the sign meaning, and the change is meaningless. Therefore, OF is only meaningful for signed numbers. Finally, with the above introduction, we can understand that SF is looking at the sign-bit meaning of the highest bit. For unsigned numbers, the highest bit represents the numerical meaning rather than the symbolic meaning.


④ Lovely and terrible C language. Why is it c again? Since most of the signed or unsigned problems we encounter are caused by signed and unsigned declarations in C, why start with assembly? Because all the c compilers we use today compile C code into assembly language code, which is then assembled into machine code using an assembler. Make clear the assembly, is equivalent to understand C fundamentally, and, with machine thinking to consider the problem, must use assembly. (MY usual problem with weird C is compiling it into assembly.) C is cute because it follows the KISS principle and abstracts the machine just enough to allow us to improve our thinking level (which is much more human than the machine level of assembly) without being too far away from the machine (which is C #, Java, etc.). The original K&R version of C was a slightly more advanced assembly… 🙂 C is scary because it reflects everything at the machine level, such as the unsigned problem (Java does not have this problem because it is designed to make all integers signed). To illustrate the horror of C, here is an example:

#include <stdio.h> 
#include <string.h> 
int main(a)
{
int x = 2; 
char * str = "abcd"; 
int y = (x - strlen(str) ) / 2;
// Note: the compiler may optimize it by using the right shift instruction instead of the division instruction
printf("%d\n",y);
}
Copy the code

It should have been -1 but instead it was 2147483647. Why is that? Since strlen returns a value of type size_t, which is an unsigned int, when mixed with an int, an int is automatically converted to an unsigned int. Looking at the compiled code, the division instruction is div, which means unsigned division. Int y = (int)(x-strlen (STR)) / 2; Force the conversion to the signed direction (the compiler defaults to the opposite) so that the division instruction is compiled to idiV. As we know, is the same state of two memory units, with signed processing instructions imul, idiv, etc., and with unsigned processing instructions muL, div, etc., the result is completely different! So be careful when it comes to signed and unsigned computations, especially when there are pesky automatic conversions! (There is no prompt for either GCC or CL when converting automatically!!) To avoid these errors, make sure your variables are signed whenever you perform operations.


2.Conditional branches Note: Greater and less are signed; above and below are unsigned. Note: Principle: Always judge first! Test then decides whether to turn to else(The top one is conditional control transfer)


Conditional move Conditional move

Note: This is a branch predictive optimization technique. The basic idea is to execute both the THEN code and the else to get two results, and then choose which result to use. This may seem like a waste of time, but the truth is that simple calculations are more efficient, and you’ll see why when you learn about performance optimization. This is a kind of assembly line technology, when the code runs to a branch, branch as a result, they try to guess this is called the branch prediction technology, and they are very good at predicting, 98% of the time they can guess right, so they can predict suta curve in the road, and began to move in this direction, as long as guess right, will be very efficient, But if the branch guesses wrong, it must be stopped and restarted in another direction.

3. The Loops loop Do the while:


While:


For:

4. A switch statementThe Switch statement uses the Jump Table mechanism, which avoids the need to determine each case(O [n]) sequentially [or the binary algorithm O(logn)], and instead hops directly to that block of code (case(O(1)).Note: the switch statement always uses ja (Max of x) to determine whether it is the default. If it is the default, skip to the default. If it is not the default, use the jump table mechanism to look up the jump table. If it doesn't start at 0, then it's given an offset. If case values are sparse, the compiler optimizes for if-else statements

Procedures

Stack is special, he is from the high address to grow down. Retq: rip pass data: rdi rsi RDX RCX R8 R9 pass data, excess pass on the stack (7th on the top of the stack). The argument requirement here is an integer or a pointer. Floating point arguments are passed by a separate set of registers. If a Single threaded model is used, the stack will be pressed continuously. Only one function will be running at any time. When the function returns, it will return the address at the top of the stack. So you can do complex work by constantly calling and returning functions. Stack frame: The stack frame is the part of the stack that is added to the function before the return. It includes the local variables in the function, the return address of the function when it calls other functions, and the parameters passed when the number of parameters exceeds 6. All stack memory allocated when this function is in control We often see that programs often allocate more space on the stack than they need, and that’s because there are conventions that require memory addresses to be aligned, and there are many ways to align, which is a little bit vague, But don’t worry about whether you have unused space and functions (don’t need to understand right now).< maybe one of the reasons is canary > RSP and RBP:

In the stack, all we need is to keep one stack frame in the stack for each procedure that is called and does not return. Usually a stack frame is separated by two Pointers, a stack pointer RSP and a base pointer RBP, but the base pointer is optional and is not usually used except in very special cases, so this register will not actually appear in your program as a frame pointer, it will be used as a regular register.

If you allocate a fixed stack frame, such as 16, then the compiler will free up that space at the end. But in the case of a variable-length array or memory buffer, the compiler does not know how much space to allocate, so it takes the base pointer to record the stack frame at the beginning, and then returns the RPS = base pointer at the end

Saved by the caller:(RBP, RBX,r12~r13), for example, if A calls B, if B might change these registers in A, then B will be pushed first. Wipe the bottom for the callerThis is a bit confusing. The reason why constant functions and constant arguments should be as const as possible is to let the compiler know that they won't change, so it doesn't have to save them.

For example, if A calls B and the call to B might change the value of these registers, save them before A calls B.

I’ll stop here today and continue tomorrow.

4. Data

Content:

Fifth, the Advanced switchable viewer

Content: