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>

これは、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