zoukankan      html  css  js  c++  java
  • 【01:55】他 个人觉得 汇编语言讲的比较好的教程是 VeryCD(电驴)上 清华大学的网上教育的一套教程 是由清华同方制作的
    
    【03:45】第一章 AT&T汇编语法格式
    1、寄存器引用
    引用寄存器要在寄存器号前加 %,如 mov %eax,%ebx
    
    2、操作数顺序
    操作数顺序 是从源(左)到目的(右),如 mov %eax(源),%ebx(目的)
    
    3、常数/立即数的格式
    使用立即数,要在数前面加 $,如 mov $4,%ebx
    符号常数直接引用,如 mov value,%ebx
    引用符号地址在符号前加 $,如 mov $value,%ebx
    
        【05:15】如果立即数前面不加 $,它认为这是一个内存地址
        ZC:如果是16进制的数,该如何表示?$4H?$0x4?
        【05:35】ZC:value 如果是个变量,行不行?
        【06:15】ZC:intel汇编格式 代表变量的地址不使用"$",用什么表示?内嵌汇编貌似是直接 &取地址?    貌似是"lea"指令。
    
    4、操作数的长度
    操作数的长度用加在指令后的符号表示
    b(byte),w(word),l(long),如 movw %ax,%bx
    
        ZC:默认情况下,AT&T格式的 mov指令的操作数的长度是32位?还是说32位的系统里面默认是32位,64位系统里面默认是64位?还是说 上面的是作者的手误,AT&T中没有单纯的"mov"指令?
        【07:25】【07:45】Intel中是明确的使用"byte ptr"或者"word ptr"。
    
    
    
    “
    ● 在AT&T汇编格式中,绝对转移和调用指令(jmp/call)的操作数前面要加上"*"作为前缀
    ● 远转移指令和原调用指令的操作码,在AT&T汇编格式中为"ljmp"和"lcall",而在Intel汇编格式中则为"jmp far"和"call far"
    
    AT&T格式
    ljmp $section,$offset
    lcall $section,$offset
    
    Intel格式
    jmp far section:offset        【09:10】跳转到 section段的offset偏移的地址处
    call far section:offset        【09:18】调用 section段的offset偏移 这个地方的函数
    
    ● 远程返回指令
    lret $stack_adjust
    ret far stack_adjust    【10:00】stack_adjust ==> 堆栈的数量(堆栈的栈帧数)
    
    ● 寻址指令
    section:disp(base, index, scale) 表示,计算方法是 base + index * scale + disp
    section:[base + index * scale +disp]
    
    movl -4(%ebp), %eax        mov eax, [ebp - 4]
    movl array(, %eax, 4), %eax    mov eax, [eax * 4 + array]
    movw array(%ebx, %eax, 4), %cx    mov cx, [ebx + 4 * eax + array]
    movb $4,%fs:(%eax)        mov fs:eax, 4
    ”
        ZC: 上面的AT&T语句中的 立即数,不是应该写成 "$-4"和"$4"的么?为何这里可以不要"$"?
    
        【08:20】在Intel格式中 jmp/call后面直接接立即数就可以了
    
        ZC: 网上查到说,在AT&T格式中,如果 jmp/call后面 不加上"*"就是 间接寻址(指令中的操作数是当做偏移量来使用的);如果 jmp/call后面 加上"*"就是 直接寻址(指令中的操作数是当做绝对地址来使用的)。
    
        【13:25】ZC: 为何这里 %fs段的偏移为 %eax?∵ AT&T中 (%eax)等价于%eax
    
    
    
    
    【13:36】
    “
    AT&T格式的 嵌入式汇编(C语言)
    
    ● _asm_("asm statements" : outputs : inputs : registers-modified);
    ● _asm_("pushl %%eax 
    	"
    "movl $0, %%eax 
    	"
    "popl %eax");
    
    {register char _res;
    asm("push %%fs
    	"
    "movw %%ax, %%fs
    	"
    movb %%fs:%2, %%al
    	"
    pop %%fs"
    :"=a(res):"0"(seg),"m"(*(addr)));
    _res;}
    
    int main()
    {
        int a1 = 10, b1 = 0;
        _asm_("movl %1, %%eax;\n\t"
        "movl %%eax, %%ecx;"
        :"=a"(b1)
        :"b"(a1)
        :"%eax");
        printf("Result : %d, %d\n", a1, b1);
    }
    
    "a"、"b"、"c"、"d" 分别表示寄存器eax、ebx、ecx和edx
    "S"和"D"    寄存器esi、edi
    "r"        任何寄存器    【25:30】如果可用 都可以用
    "0"        【25:35】表示与上面寄存器相同位置使用同一个寄存器(ZC: 这里就是指 与第0个寄存器使用同一个寄存器,第0个寄存器 是什么寄存器 这里也就是什么寄存器)
    ”
        ZC: 上面怎么一会"pushl",一会"push"?
        ZC: 两个 % 是什么意思?
        ZC: “movb %%fs:%2, %%al
    	"”这一句,前面少了一个双引号吧?
            ZC: "%2"是什么意思?不是"$2"或"2"? (【17:45】处有讲解,去掉一个%就是数值2了,但是为何不是写成“movb %%fs:%$2, %%al”?∵它不是指立即数,是指第2个参数,见 【22:10】和【23:53】)
        ZC: “pop %%fs"”这一句,前面少了一个双引号吧?
        ZC: 为何 有时是"\n"和"\r",有时又是"
    "和"
    ",他们不是都在双赢好里面的么,有什么区别?
        ZC: 有时 汇编语句最后带一个分号,有时又不带??
    
    “_asm_("asm statements" : outputs : inputs : registers-modified);”
        【14:00】_asm_ 和 asm 表示的意义 是相同的
        【14:10】引号引起来的部分是用到的汇编语句。这个汇编语句 可以是多条,每一条汇编语句 前后用引号引起来 在最后加上"
    	"。或者,把多条汇编语句,每条汇编语句 后面用分号分开,然后 第一条语句的前面 和 最后一条语句的后面 加上引号就可以了。
        【14:45】有3个冒号,每个冒号为一条语句。这3个是可选项,任何一项不使用 我们就把它省略掉,【15:03】如果中间那个省略掉就写成
            “_asm_("asm statements" : outputs : : registers-modified);”
            如果前两项省略掉就写成
            “_asm_("asm statements" : : : registers-modified);”
            【15:18】第一个冒号“:outputs”,表示在代码"asm statements" 执行完毕之后 将会用来输出的寄存器是哪一个。一般输出的寄存器后面 都接一个变量,把这个输出寄存器的内容赋给这个变量。
            【15:38】第二个冒号“:inputs”,表示在代码"asm statements" 执行之前,我们需要输入的参数(这段代码"asm statements"需要用到的参数)。【15:55】这个,输入的寄存器一般也是接一个变量,把这个变量的值 赋给 寄存器。
            【16:00】第三个冒号“:registers-modified”,表示代码"asm statements" 执行的过程中,会被修改的寄存器。
    
        【16:15】格式介绍完毕,举几个例子看一下。
    
    “
    _asm_("pushl %%eax 
    	"
    "movl $0, %%eax 
    	"
    "popl %%eax");        ZC:这里少一个 %
    ”
        【17:45】前面提到过 在寄存器前面加一个%,在嵌入式汇编里面为何要加2个呢?∵ gcc在编译C语言源程序的时候,它首先把C语言源程序 变成中间的一些格式(比如说汇编格式,目标格式),它在转换格式的时候 会把嵌入式汇编里面的%先去掉一个 然后输出纯汇编格式的,这样 输出纯汇编格式的时候就变成一个%了
    
    “
    {register char _res;
    asm("push %%fs
    	"
    "movw %%ax, %%fs
    	"
    movb %%fs:%2, %%al
    	"
    pop %%fs"
    :"=a(res):"0"(seg),"m"(*(addr)));
    _res;}
    ”
        【18:40】定义一个寄存器变量_res (ZC:寄存器变量是指 使用寄存器而非内存的变量?)
        【18:50】这一段是嵌入式汇编:
            “
                asm("push %%fs
    	"
                “movw %%ax, %%fs
    	”
                movb %%fs:%2, %%al
    	"
                pop %%fs"
                :"=a(res):"0"(seg),"m"(*(addr)));
            ”
        【19:23】等号"=" 表示 指明哪个是输出寄存器
        【19:55】seg 和 addr 是前面定义的变量,【20:00】seg为整型,【20:06】ZC:addr是什么类型的变量听不清楚...难道是character类型变量?【20:08】一个字符串。
        【20:29】"0" 表示 与前面输出寄存器相同位置 使用同一个寄存器,也就是说它在输入寄存器里面是排在第一位的
            ZC: 这里讲到的"输出寄存器相同位置",难道是说 0就是指第0个输出寄存器?
            ZC: 那上面说的"排在第一位的"又如何理解?
        【20:50】"m" 表示 这是一个内存地址 把 *(addr) 一个内存地址
        【21:15】输出寄存器 和 输入寄存器 是按照 从0到9排序的。
            【21:23】这里 输出寄存器,只有一个所以它是0。
            【21:25】ZC: 这里 输出寄存器 和 输入寄存器 是放在一起 从0到9排序的,并非 各自单独从0到9排序 ! ! 所以这里 seg是将值给了 第1个寄存器,又∵第1个寄存器==第0个寄存器==eax,也就是 seg将值给了eax。
    
        【22:10】“movb %%fs:%2, %%al”
            fs段 %2,%2 表示 第二号/序号2。把 fs指向的段,偏移地址为addr 的地址取出一个字节 放到al中
            ZC: 偏移地址为何不是 *(addr),而是 addr?
    
        【22:43】“_res;”
            ZC: 由 说是返回_res的意思,又没有return 直接一个“_res;”就表示返回_res?
    
        ZC: 经过我的修改后,我觉得正确的代码应该是这样:
        “
            {
            register char _res;
            asm("push %%fs
    	"
            "movw %%ax, %%fs
    	"
            "movb %%fs:%2, %%al
    	"
            "pop %%fs"
            :"=a"(res):"0"(seg),"m"(*(addr)));
            _res;
            }
        ”
    
    
    【22:52】
    “
    int main()
    {
        int a1 = 10, b1 = 0;
        _asm_("movl %1, %%eax;\n\t"
        "movl %%eax, %%ecx;"
        :"=a"(b1)
        :"b"(a1)
        :"%eax");
        printf("Result : %d, %d\n", a1, b1);
    }
    ”
        【23:53】“%1”表示 第一号参数(ZC: 那就是 ebx/a1 了)
        【24:45】这段内嵌汇编代码(ZC: 两个movl指令)执行完毕之后,把eax中的内容赋给了b1。这时 b1也就等于10了,打印出来 a1值为10,b1值为10.
    
    
    
    
    
    
    【完毕】

    C

  • 相关阅读:
    LeetCode 461. Hamming Distance
    LeetCode 442. Find All Duplicates in an Array
    LeetCode 448. Find All Numbers Disappeared in an Array
    LeetCode Find the Difference
    LeetCode 415. Add Strings
    LeetCode 445. Add Two Numbers II
    LeetCode 438. Find All Anagrams in a String
    LeetCode 463. Island Perimeter
    LeetCode 362. Design Hit Counter
    LeetCode 359. Logger Rate Limiter
  • 原文地址:https://www.cnblogs.com/CodeSkill/p/5041802.html
Copyright © 2011-2022 走看看