https://github.com/akkartik/mu/blob/master/019functions.cc
  1 //:: call
  2 
  3 :(before "End Initialize Op Names")
  4 put_new(Name, "e8", "call disp32 (call)");
  5 
  6 :(code)
  7 void test_call_disp32() {
  8   Mem.push_back(vma(0xbd000000));  // manually allocate memory
  9   Reg[ESP].u = 0xbd000064;
 10   run(
 11       "== code 0x1\n"
 12       // op     ModR/M  SI
// "a type" "needed java_imports"
an id="L51" class="LineNr"> 51 "run: r/m32 is EBX\n" 52 "run: decrementing ESP to 0xbd000060\n" 53 "run: pushing value 0x00000003\n" 54 "run: jumping to 0x000000a3\n" 55 ); 56 } 57 58 :(before "End Op ff Subops") 59 case 2: { // call function pointer at r/m32 60 trace(Callstack_depth+1, "run") << "call to r/m32" << end(); 61 const int32_t* offset = effective_address(modrm); 62 push(EIP); 63 EIP += *offset; 64 trace(Callstack_depth+1, "run") << "jumping to 0x" << HEXWORD << EIP << end(); 65 ++Callstack_depth; 66 break; 67 } 68 69 :(code) 70 void test_call_mem_at_r32() { 71 Mem.push_back(vma(0xbd000000)); // manually allocate memory 72 Reg[ESP].u = 0xbd000064; 73 Reg[EBX].u = 0x2000; 74 run( 75 "== code 0x1\n" 76 // op ModR/M SIB displacement immediate 77 " ff 13 \n" // call function offset at *EBX 78 // next EIP is 3 79 "== data 0x2000\n" 80 "a0 00 00 00\n" // 0x000000a0 81 ); 82 CHECK_TRACE_CONTENTS( 83 "run: call to r/m32\n" 84 "run: effective address is 0x00002000 (EBX)\n" 85 "run: decrementing ESP to 0xbd000060\n" 86 "run: pushing value 0x00000003\n" 87 "run: jumping to 0x000000a3\n" 88 ); 89 } 90 91 //:: ret 92 93 :(before "End Initialize Op Names") 94 put_new(Name, "c3", "return from most recent unfinished call (ret)"); 95 96 :(code) 97 void test_ret() { 98 Mem.push_back(vma(0xbd000000)); // manually allocate memory 99 Reg[ESP].u = 0xbd000064; 100 write_mem_u32(Reg[ESP].u, 0x10); 101 run( 102 "== code 0x1\n" 103 // op ModR/M SIB displacement immediate 104 " c3 \n" // return 105 "== data 0x2000\n" 106 "10 00 00 00\n" // 0x00000010 107 ); 108 CHECK_TRACE_CONTENTS( 109 "run: return\n" 110 "run: popping value 0x00000010\n" 111 "run: jumping to 0x00000010\n" 112 ); 113 } 114 115 :(before "End Single-Byte Opcodes") 116 case 0xc3: { // return from a call 117 trace(Callstack_depth+1, "run") << "return" << end(); 118 --Callstack_depth; 119 EIP = pop(); 120 trace(Callstack_depth+1, "run") << "jumping to 0x" << HEXWORD << EIP << end(); 121 break; 122 }