微前端架构如何改变企业的开发模式与效率提升
690
2022-08-27
汇编 —— 起步
作为非计算机专业的孩子,想要了解每一条C语句到底发生了什么,学习汇编也就变得水到渠成了。经过好几天的折腾,总算搞懂了一点点,一开始看王爽老师的《汇编语言 第三版》,讲得确实不错,但是8086cpu的汇编环境确实有点老,装了一个DOSBos,debug.exe倒是能用了,但是edit,masm啥的全都没有啊,更重要的是将来的工作都是在linux上进行,故而学到第四章就放弃了,转而学习linux环境的汇编。
语言
在操作的最底层,计算机处理器按照制造厂商在处理器芯片内部定义的二进制代码操作数据,预置的代码称之为指令码,不同的处理器包含不同类型的指令码。 高级语言分为编译语言(编译生成指令码,指令码生成可执行文件),解释语言(由单独的程序读取和执行,程序代码转换成指令码),混合语言(包含前两种语言的特点,比如java语言,编译生成字节码再由java虚拟机JVM解释)。
计算机结构
存储器由一些可变模式的容器组成。 晶体管开关及其支持部件合在一起称之为存储单元。 计算机中的成员:晶体管、二极管、硅、半导体、电容。 Intel的32位体系结构叫做IA-32,AMD创造的向后兼容的64位x86体系结构就做x86_64. cpu为了完成指令让它做的事情而依赖的所有的电机制统称为CPU的微体系结构。 操作系统可以为任务列表中的每一个程序赋予一个优先级,高优先级的任务获得更多的时钟周期,低优先级的任务获得较少的时钟周期。 linux内核和图形用户界面是完全分开的,系统寄存器或被标识为内核空间,或被标识为用户空间,运行在用户空间的任何内容都不能被写入内核空间中,也不能从内核空间读取内容。只有运行在内核空间中的软件才能直接访问物理硬件。 CPU的效率取决于它一次能调集的地址线根数。
寄存器
IA-32处理器
寄存器 | 作用 |
通用 | 8个32位用于存储数据的存储器 |
段 | 6个16位处理内存访问的寄存器 |
指针 | 32位寄存器,指向下一条指令码 |
浮点数据 | 8个80位寄存器,用于浮点数学计算 |
控制 | 5个32位用于确定处理器操作模式的处理器 |
调试 | 8个32位包含调试信息的处理器 |
32位x86体系结构的8个通用寄存器:EAX, EBX, ECX, EDX, EBP, ESI, EDI, ESP.
通用寄存器 | 作用 |
EAX | 操作数和结果数据的累加器 |
EBX | 指向数据段内存中数据的指针 |
ECX | 字符串和循环操作的计数器 |
EDX | I/O指针 |
EDI | 字符串操作的目标的数据指针 |
ESI | 字符串操作的源的数据指针 |
ESP | 堆栈指针 |
EBP | 堆栈数据指针 |
通用寄存器:
半寄存器:
指针寄存器:EIP寄存器,跟踪下一条指令码。
段寄存器 | 作用 |
CS | 代码段 |
DS | 数据段 |
SS | 堆栈段 |
ES | 附加段指针 |
FS | 附加段指针 |
GS | 附加段指针 |
控制寄存器 | 描述 |
CR0 | 控制操作模式和处理器状态的系统标志 |
CR1 | |
CR2 | 内存页面错误信息 |
CR3 | 内存页面目录信息 |
CR4 | 说明处理器特性或能力的标志 |
内存
RAM: 随机访问存储,不会影响其他内容,就像在图书馆检索后找书一样。 ROM: 顺序访问,依次搜索。 一旦一个内存地址被应用到地址管脚上,数据管脚就会发生变化。 一个字节(byte)由8位(bit)
名称 | 内存单元 |
字节 | 1 |
字 | 2 |
双字 | 4 |
四字 | 8 |
十字节 | 10 |
段落 | 16 |
页 | 256 |
段 | 65536 |
字单元:存放一个字型数据的内存单元,16位,由两个连续的内存单元组成。 任何两个连续的内存单元都可以看作一个字单元。 一次处理双字的计算机即32位,一次处理4字的计算机就是64位,多少位就是针对处理器来说的。 中央处理单元(CPU)从内存中独入一个字节(双字、四字等)时,它将该字节的内存地址放到他的地址管脚上,编码成二进制数,字节随后出现在数据管脚上。 每一个CPU都含有存储数据的地方,称之为寄存器。 cpu在指针寄存器的指引下行进,其工作的本质就是将不同的机器指令字节压入8个晶体管寄存器中。 数据总线上一根线对应1位(bit),地址总线上对应一个存储单元 (字节,byte) cpu在段地址中进行读写操作就是在物理存储器中进行读写操作。 地址总线影响着内存的大小。
内存 | 段地址 | 偏移地址 |
数据段 | DS | SI |
代码段 | CS | IP |
栈段 | SS | SP |
一段内存可以同时是代码段、数据段、栈空间,也可以啥也不是。
使用gdb查看内存地址的存储值:
$ gdb exe(gdb) startTemporary breakpoint 1 at 0x804845c: file x.c, line 4.Starting program: /home/edemon/workspace/exe Temporary breakpoint 1, main () at x.c:44 char *p = (char *)malloc(1);(gdb) n5 *p = 'a';(gdb) p p$1 = 0x804b008 ""(gdb) help xExamine memory: x/FMT ADDRESS.ADDRESS is an expression for the memory address to examine.FMT is a repeat count followed by a format letter and a size letter.Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char), s(string) and z(hex, zero padded on the left).Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).The specified number of objects of the specified size are printedaccording to the format.Defaults for format and size letters are those previously used.Default count is 1. Default address is following last thing printedwith this command or "print".(gdb) x/1ub 0x804b0080x804b008: 0(gdb) x/1ub 0xb7fbd0a00xb7fbd0a0
段寄存器是操作系统的工具。
汇编
intel处理器官网:intel.com 反汇编(Disassembly):把目标代码转为汇编代码的过程 下面是汇编学习环境:
tool | info | use example |
汇编器 | AS - the portable GNU assembler | as -o test.o test.s |
连接器 | ld - The GNU linker | ld -o test test.o |
调试器 | gdb - The GNU Debugger | gdb a.out |
编译器 | gcc - GNU project C and C++ compiler | gcc hello.c |
反汇编器 | objdump - display information from object files | objdump -d a.out > a.s |
分析器 | gprof - display call graph profile data | goto tag; ^_^ |
分析器的三类文件:
FILES "a.out" the namelist and text space. "gmon.out" dynamic call graph and profile. "gmon.sum" summarized dynamic call graph and
tag: 分析器的使用如下:
edemon@ubuntu1:~/workspace$ gcc hello.c -pg -o hello -O2 -lcedemon@ubuntu1:~/workspace$ ./hellohelloedemon@ubuntu1:~/workspace$ ls |grep gmongmon.outedemon@ubuntu1:~/workspace$ gprof hello gmon.out -pFlat profile:Each sample counts as 0.01 seconds. no time accumulated % cumulative self self total time seconds seconds calls Ts/call Ts/call name % the percentage of the total running time of thetime program used by this function.cumulative a running sum of the number of seconds accounted seconds for by this function and those listed above it. self the number of seconds accounted for by thisseconds function alone. This is the major sort for this
GNU连接器ld查找的是_start来确定程序开始的位置,但是gcc查找的是main标签,所以我们需要修改: 所以如果是使用gcc汇编和连接汇编程序,那么将_start改成main即可。 调试汇编程序,as的调试选项[--gstabs+] [--gdwarf-2] [--gdwarf-sections]。 例如: as -gstabs -o test.o test.s gdb中使用print打印2进制、10进制、16进制的格式:print/t, print/d, print/x 系统:Linux ubuntu1 3.19.0-74-generic #82-Ubuntu SMP Thu Oct 20 21:46:04 UTC 2016 i686 i686 i686 GNU/Linux 标准的C动态库文件:/lib/i386-linux-gnu/libc.so.6
Intel和AT&T的区别: AT&T使用$表示立即操作数,Intel不需要。 AT&T在寄存器名称前使用&,Intel不需要。 AT&T的source、destination的顺序和Intel是相反的,比如AT&T的mov: movx source, destination, Intel的mov:mov desctination, source AT&T在助记符后面使用单独的字符表示数据长度,而Intel使用单独的操作数表示长度。 定义段和偏移值,AT&T: ljmp $section,$offset, Intel使用 jmp section:offset。
第一个程序
和高级语言不同的是,在汇编中写一个“hello world”不再是一件容易的事情。我的第一个汇编程序是简单的寄存器存值(够简单吧)。 内容:
.section .text.global mainmain:movl $100, %eaxint $0x80
int $0x80是一个Linux系统调用,从内核访问控制台显示。 用gdb执行并查看寄存器的值
[edemon@CentOS asm]$ gcc -gdwarf-2 -o mov mov.s[edemon@CentOS asm]$ gdb movGNU gdb (GDB) Red Hat Enterprise Linux (7.2-90.el6)...Starting program: /home/edemon/workspace/asm/mov Temporary breakpoint 1, main () at mov.s:44 movl $100, %eaxMissing separate debuginfos, use: debuginfo-install glibc-2.12-1.192.el6.i686(gdb) n5 int $0x80(gdb) info registereax 0x64 100ecx 0xeb17dccc -350757684edx 0x1 1ebx 0x3a3ff4 3817460esp 0xbffff22c 0xbffff22cebp 0xbffff2a8 0xbffff2a8esi 0x0 0edi 0x0 0eip 0x80483f1 0x80483f1
可以发现eax已经变成100.
hello world汇编: 两天之后,我发现linux下的AT&T汇编hello world原来也挺简单的 (多亏能调用C的函数)。哈哈哈,总算入门了。(16.12.20)
.section .dataoutput: .asciz "hello world\n".section .text.globl mainmain: pushl $output call printf call
编译执行:
[edemon@CentOS workspace]$ gcc cmov.s[edemon@CentOS workspace]$ ./a.out hello world
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~