2

我已经为 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 }
4

0 回答 0