# Mu - subx/019functions.cc

     1 //:: call
     2
     3 :(before "End Initialize Op Names")
     4 put_new(Name, "e8", "call disp32 (call)");
     5
     6 :(scenario call_disp32)
     7 % Reg[ESP].u = 0x64;
     8 == 0x1
     9 # op  ModR/M  SIB   displacement  immediate
    10   e8                              a0 00 00 00  # call function offset at 0x000000a0
    11   # next EIP is 6
    12 +run: call imm32 0x000000a0
    13 +run: decrementing ESP to 0x00000060
    14 +run: pushing value 0x00000006
    15 +run: jumping to 0x000000a6
    16
    17 :(before "End Single-Byte Opcodes")
    18 case 0xe8: {  // call disp32 relative to next EIP
    19   const int32_t offset = next32();
    20   trace(90, "run") << "call imm32 0x" << HEXWORD << offset << end();
    21 //?   cerr << "push: EIP: " << EIP << " => " << Reg[ESP].u << '\n';
    22   push(EIP);
    23   EIP += offset;
    24   trace(90, "run") << "jumping to 0x" << HEXWORD << EIP << end();
    25   break;
    26 }
    27
    28 //:
    29
    30 :(scenario call_r32)
    31 % Reg[ESP].u = 0x64;
    32 % Reg[EBX].u = 0x000000a0;
    33 == 0x1
    34 # op  ModR/M  SIB   displacement  immediate
    35   ff  d3                                       # call function offset at EBX
    36   # next EIP is 3
    37 +run: call to r/m32
    38 +run: r/m32 is EBX
    39 +run: decrementing ESP to 0x00000060
    40 +run: pushing value 0x00000003
    41 +run: jumping to 0x000000a3
    42
    43 :(before "End Op ff Subops")
    44 case 2: {  // call function pointer at r/m32
    45   trace(90, "run") << "call to r/m32" << end();
    46   const int32_t* offset = effective_address(modrm);
    47   push(EIP);
    48   EIP += *offset;
    49   trace(90, "run") << "jumping to 0x" << HEXWORD << EIP << end();
    50   break;
    51 }
    52
    53 :(scenario call_mem_at_r32)
    54 % Reg[ESP].u = 0x64;
    55 % Reg[EBX].u = 0x2000;
    56 == 0x1  # code segment
    57 # op  ModR/M  SIB   displacement  immediate
    58   ff  13                                       # call function offset at *EBX
    59   # next EIP is 3
    60 == 0x2000  # data segment
    61 a0 00 00 00  # 0xa0
    62 +run: call to r/m32
    63 +run: effective address is 0x00002000 (EBX)
    64 +run: decrementing ESP to 0x00000060
    65 +run: pushing value 0x00000003
    66 +run: jumping to 0x000000a3
    67
    68 //:: ret
    69
    70 :(before "End Initialize Op Names")
    71 put_new(Name, "c3", "return from most recent unfinished call (ret)");
    72
    73 :(scenario ret)
    74 % Reg[ESP].u = 0x2000;
    75 == 0x1  # code segment
    76 # op  ModR/M  SIB   displacement  immediate
    77   c3
    78 == 0x2000  # data segment
    79 10 00 00 00  # 0x10
    80 +run: return
    81 +run: popping value 0x00000010
    82 +run: jumping to 0x00000010
    83
    84 :(before "End Single-Byte Opcodes")
    85 case 0xc3: {  // return from a call
    86   trace(90, "run") << "return" << end();
    87   EIP = pop();
    88   trace(90, "run") << "jumping to 0x" << HEXWORD << EIP << end();
    89   break;
    90 }