Linux 2.4.16 kernel strcmp
static inline int strcmp(const char * cs,const char * ct) { int d0, d1; register int __res; __asm__ __volatile__( "1:\tlodsb\n\t" "scasb\n\t" "jne 2f\n\t" "testb %%al,%%al\n\t" "jne 1b\n\t" "xorl %%eax,%%eax\n\t" "jmp 3f\n" "2:\tsbbl %%eax,%%eax\n\t" "orb $1,%%al\n" "3:" :"=a" (__res), "=&S" (d0), "=&D" (d1) :"1" (cs),"2" (ct)); return __res; }
"\ N" is a line break and "\ t" is a tab character. Add these two symbols at the end of each command, it is to let gcc translate embedded assembly code into General Assembly Code to ensure line breaks and leave some spaces. For example, the above embedded assembly will be translated:
1: lodsb |
// Load the string operand, that is, transfer the esi character from the DS segment to the al register, and then the esi points to the next element in the string according to DF, DF = 0, increase; DF = 1, decrease |
Scasb |
// Number OF scanned string operations, that is, the edi position characters in the ES segment are subtracted from the al. The results are not retained. Only the signs CF, AF, PF, SF, OF, ZF, if the characters are equal, ZF = 1; otherwise, ZF = 0. If the number of characters in the DS segment is less than the string in the ES segment, CF = 1, followed by the sbb operation will show-1 |
Jne2f |
// If the two characters are not equal |
Testb % al |
// If all values in al are 0, ZF = 1 (the logic and result are 0). If the string ends, null is null. |
Jne 1b |
// If ZF = 0 (the logic and result are not 0), that is, the string is not ended, the comparison is continued. |
Xorl % eax |
// Exclusive or, the result is 0, CF = 0, and eax is cleared |
Jmp 3f |
// Jump forward to 3:, exit, return value is 0 |
2: sbbl % eax |
// 32-bit sbb src, dest; dest-src-CF, stored in dest. If CF = 1, the result is-1 (all 1); otherwise, it is 0. (When the result is-1, the flag is: CF = 1, SF = 1, OF = 1, ZF = 0, PF = 1) |
Orb $ 1% al |
// For 0 or 1, ensure that the result is-1 or 1. If the result is 0, or 1 is followed by 1, that is, if the character is large, 1 is returned, and the character is small,-1 is returned. |
3: |
|
This code looks very familiar and is not difficult to read. 3f indicates that the first line marked as 3 is found in the forward (forword). Accordingly, 1b indicates finding the line later. The combination of output and input in Embedded Assembly Code is: Return Value _ res, which is placed in the al register and combined with % 0; local variable d0, which is combined with % 1, it also corresponds to the input cs parameter and is stored in the register ESI, that is, the starting address of the source string in ESI. The local variable d1, combined with % 2, corresponds to the ct parameters of the input part, and is also stored in the register EDI, that is, the starting address of the target string in EDI. Through the analysis of this piece of code, we should understand that the hacker is unfavorable. The difference between Embedded Assembly and General Assembly is only the form, and the essence remains unchanged. Therefore, fully understanding Intel 386 Assembly commands is beyond the root of low-level code reading. Most commands use the following suffixes for AT&T: B bytes (8 bits ), corresponding to Intel's byte ptr w (16 bits), corresponding to Intel's word ptr l dual (actually long, 32 bits ), corresponding to Intel's dword ptr q four-character (64-bit), corresponding to Intel's qword ptr