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

  • 相关阅读:
    L391 弦理论
    L390 Business meeting English
    L389 ABDDC
    L388 Five Ways to Manage Travel Sickness
    L386 DACBD
    Spring 中拦截器与过滤器的区别
    Hibernate中,left join、inner join以及left join fetch区别(转)
    java读取配置文件的几种方法
    Struts1和Struts2的区别和对比(完整版)
    面试题之String str = new String("abc"); 创建了几个对象
  • 原文地址:https://www.cnblogs.com/CodeSkill/p/5041802.html
Copyright © 2011-2022 走看看