我已经为 printf 编写了自己的代码。我使用的是 64 位机器。我正在尝试打印指针地址。出于某种原因,我只得到了低 32 位地址。你能帮我为什么我没有得到完整的地址吗?到目前为止我的发现。
Breakpoint 1, kprintf (fmt=0xffffffff00201687 "%p") at sys/main.c:249
249 write_string(0x1F,"0x");
(gdb) p /x addr
$1 = 0xffffffff002050f4
这是我对应的代码。
247 case 'p': addr = va_arg(arg_p, uint64_t); // Print Address of the pointer
248 //addr = (uint64_t) v;
249 write_string(0x1F,"0x");
250 write_string(0x1F,convert(addr,16));
251 break;
奇怪的是,我发现 convert 函数的参数实际上是通过 %edi寄存器传递的,这就是我得到 32 位值的原因。但我想知道为什么没有通过 %rdi 寄存器。这是我的 objdump / 反汇编
658 ffffffff00200a34: 48 89 44 24 08 mov %rax,0x8(%rsp)
659 ffffffff00200a39: be 0a 00 00 00 mov $0xa,%esi
660 ffffffff00200a3e: 8b 39 mov (%rcx),%edi
661 ffffffff00200a40: e8 c3 01 00 00 callq ffffffff00200c08 <convert>
这就是我在转换函数中接收参数的方式。
13 char *convert(uint64_t num, int base)
14 {
有人可以告诉我这里的问题吗?
编辑:添加更多代码
int kprintf(char *fmt,...){
char *p;
uint64_t addr;
int i; // integer argument
char *s; // string argument
va_list arg_p; // pointer to the variable argument list
va_start(arg_p, fmt);
for(p=fmt; *p ; p++){
if(*p != '%'){
write_char(0x1F,*p);
continue;
}
switch(*++p){
case 'p': addr = va_arg(arg_p, uint64_t); // Print Address of the pointer
//addr = (uint64_t) v;
write_string(0x1F,"0x");
write_string(0x1F,convert(addr,16));
break;
}
我的 va_list
1 #define va_start(v,l) __builtin_va_start(v,l)
2 #define va_arg(v,l) __builtin_va_arg(v,l)
3 #define va_end(v) __builtin_va_end(v)
4 #define va_copy(d,s) __builtin_va_copy(d,s)
5 typedef __builtin_va_list va_list;
我打电话给我的 krpintf 如下
kprintf("%p",(uint64_t)&i);
最后,我的转换功能是
13 char *convert(uint64_t num, int base)
14 {
15 static char buf[65];
16 char *ptr;
17
18 ptr=&buf[sizeof(buf)-1];
19 *ptr='\0';
20 do
21 {
22 *--ptr="0123456789abcdef"[num%base];
23 num/=base;
24 }while(num!=0);
25 return(ptr);
26 }