命令gcc -S -m32 lab0_ex1.c
-S
把文件编译成为汇编代码-m32
编译成32位程序,在64位机器需要指定lab0_ex1.c
下的内容
int count=1;
int value=1;
int buf[10];
void main()
{
asm(
"cld \n\t"
"rep \n\t"
"stosl"
:
: "c" (count), "a" (value) , "D" (buf[0])
:
);
}
copy
cld
clear direction 清除方向标志位(DF),DF=0表示指令执行过程中源变址寄存器(ESI)/目的变址寄存器(EDI)往增达方向移动rep
当计数寄存器(ECX)不为零,ECX=ECX-1并重复执行::stosl
stos指令是字符串处理指令的一种,即Store String Instruction,将EAX中的值保存到ES:EDI指向的地址中,根据方向标志位DF决定EDI+4/-4
这几条语句的功能是向buf中写上count个value值
asm内联语句部分符号含义
c-ECX
a-EAX
D-EDI
结果(lab0_ex1.s)
.file "lab0_ex1.c"
.globl count
.data
.align 4
.type count, @object
.size count, 4
count:
.long 1
.globl value
.align 4
.type value, @object
.size value, 4
value:
.long 1
.comm buf,40,32
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
pushl %edi
pushl %ebx
.cfi_offset 7, -12
.cfi_offset 3, -16
movl count, %edx
movl value, %eax
movl buf, %ebx
movl %edx, %ecx
movl %ebx, %edi
#APP
# 6 "lab0_ex1.c" 1
cld
rep
stosl
# 0 "" 2
#NO_APP
popl %ebx
.cfi_restore 3
popl %edi
.cfi_restore 7
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
.section .note.GNU-stack,"",@progbits
copy
CFI 即 Call Frame Information,是 DWARF 2.0 定义的函数栈信息,DWARF 即 Debugging With Attributed Record Formats ,是一种调试信息格式。 .cfi_ 开头的汇编指示符用来告诉汇编器生成相应的 DWARF 调试信息,主要是和函数有关。.cfi_startproc 定义函数开始,.cfi_endproc 定义函数结束。
原文链接:https://blog.csdn.net/zoomdy/article/details/80700750
cfi指令解析:https://sourceware.org/binutils/docs/as/CFI-directives.html、 http://www.dwarfstd.or/doc/DWARF5.pdf
命令:gcc -g -m32 lab0_ex2.c
-g
生成供调试用的可执行文件,可以在gdb中运行 lab0_ex2.c
打印“hello world”字符串
#include <stdio.h>
int
main(void)
{
printf("Hello, world!\n");
return 0;
}
copy
进入加载可执行文件a.out,启动gdb调试:gdb a.out
命令:gcc -g -m32 lab0_ex3.c 2>&1|tee make.log
2>&1
将标准错误输出重定向到标准输出
tee
从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件(make.log)
lab0_ex3.c内容:
int
main(void)
{
unsigned before;
unsigned intr;
unsigned after;
struct gatedesc gintr;
intr=8;
before=after=0;
gintr=*((struct gatedesc *)&intr);
SETGATE(gintr, 0,1,2,3);
intr=*(unsigned *)&(gintr);
printf("intr is 0x%x\n",intr);
printf("gintr is 0x%llx\n",gintr);
return 0;
}
copy
报错——类型有问题:
lab0_ex3.c: In function \u2018main\u2019: lab0_ex3.c:48:5: warning: format \u2018%llx\u2019 expects argument of type \u2018long long unsigned int\u2019, but argument 2 has type \u2018struct gatedesc\u2019 [-Wformat=] printf("gintr is 0x%llx\n",gintr);
copy
修改一:
printf("gintr is 0x%llx\n",(long long unsigned)gintr);
继续报错:
lab0_ex3.c: In function \u2018main\u2019: lab0_ex3.c:48:5: error: aggregate value used where an integer was expected printf("gintr is 0x%llx\n",(long long unsigned)gintr);
copy
原因:
C语言的类型强制转换只有在数量类型之间才能进行转换,结构类型(包括 union,struct)不是数量类型(Scalar Type),无法进行强制转换;
数量类型包括算术类型和指针类型,算术类型由包括整数类型和浮点类型。(https://blog.csdn.net/swj9099/article/details/81359690)
修改二:
printf("gintr is 0x%llx\n",*(long long unsigned*)&gintr);
得到结果(intr为32为整形,高位0省去,gintr为long long int 为64位长整型)
intr is 0x10002
gintr is ee0000010002
copy
打印的gintr为gatedesc结构体(中断门描述符)经过SETGATE(gintr, 0,1,2:,3);赋值后的结果(intr为低32位的结果),结构体gatedesc和SETGATE宏定义为:
#define STS_IG32 0xE // 32-bit Interrupt Gate
#define STS_TG32 0xF // 32-bit Trap Gate
typedef unsigned uint32_t;
#define SETGATE(gate, istrap, sel, off, dpl) { \
(gate).gd_off_15_0 = (uint32_t)(off) & 0xffff; \
(gate).gd_ss = (sel); \
(gate).gd_args = 0; \
(gate).gd_rsv1 = 0; \
(gate).gd_type = (istrap) ? STS_TG32 : STS_IG32; \
(gate).gd_s = 0; \
(gate).gd_dpl = (dpl); \
(gate).gd_p = 1; \
(gate).gd_off_31_16 = (uint32_t)(off) >> 16; \
}
/* Gate descriptors for interrupts and traps */
struct gatedesc {
unsigned gd_off_15_0 : 16; // low 16 bits of offset in segment
unsigned gd_ss : 16; // segment selector
unsigned gd_args : 5; // # args, 0 for interrupt/trap gates
unsigned gd_rsv1 : 3; // reserved(should be zero I guess)
unsigned gd_type : 4; // type(STS_{TG,IG32,TG32})
unsigned gd_s : 1; // must be 0 (system)
unsigned gd_dpl : 2; // descriptor(meaning new) privilege level
unsigned gd_p : 1; // Present
unsigned gd_off_31_16 : 16; // high bits of offset in segment
};
copy
```
学习时间 755分钟
操作时间 254分钟
按键次数 14245次
实验次数 43次
报告字数 4944字
是否完成 完成