Node.js 反汇编库使用代码中的 exampleRipHi 和 exampleRipLo 代表什么?
What do exampleRipHi and exampleRipLo represent in this Node.js disassembler library usage code?
// iced-x86 features needed: --features "decoder nasm"
const { Decoder, DecoderOptions, Formatter, FormatterSyntax } = require("iced-x86");
/*
This code produces the following output:
00007FFAC46ACDA4 48895C2410 mov [rsp+10h],rbx
00007FFAC46ACDA9 4889742418 mov [rsp+18h],rsi
00007FFAC46ACDAE 55 push rbp
00007FFAC46ACDAF 57 push rdi
00007FFAC46ACDB0 4156 push r14
00007FFAC46ACDB2 488DAC2400FFFFFF lea rbp,[rsp-100h]
00007FFAC46ACDBA 4881EC00020000 sub rsp,200h
00007FFAC46ACDC1 488B0518570A00 mov rax,[rel 7FFA`C475`24E0h]
00007FFAC46ACDC8 4833C4 xor rax,rsp
00007FFAC46ACDCB 488985F0000000 mov [rbp+0F0h],rax
00007FFAC46ACDD2 4C8B052F240A00 mov r8,[rel 7FFA`C474`F208h]
00007FFAC46ACDD9 488D05787C0400 lea rax,[rel 7FFA`C46F`4A58h]
00007FFAC46ACDE0 33FF xor edi,edi
*/
const exampleBitness = 64;
const exampleRipLo = 0xC46ACDA4;
const exampleRipHi = 0x00007FFA;
const exampleCode = new Uint8Array([
0x48, 0x89, 0x5C, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x55, 0x57, 0x41, 0x56, 0x48, 0x8D,
0xAC, 0x24, 0x00, 0xFF, 0xFF, 0xFF, 0x48, 0x81, 0xEC, 0x00, 0x02, 0x00, 0x00, 0x48, 0x8B, 0x05,
0x18, 0x57, 0x0A, 0x00, 0x48, 0x33, 0xC4, 0x48, 0x89, 0x85, 0xF0, 0x00, 0x00, 0x00, 0x4C, 0x8B,
0x05, 0x2F, 0x24, 0x0A, 0x00, 0x48, 0x8D, 0x05, 0x78, 0x7C, 0x04, 0x00, 0x33, 0xFF
]);
const hexBytesColumnByteLength = 10;
const decoder = new Decoder(exampleBitness, exampleCode, DecoderOptions.None);
// You have to enable the bigint feature to get i64/u64 APIs, not all browsers support BigInt
decoder.ipLo = exampleRipLo;
decoder.ipHi = exampleRipHi;
// This decodes all bytes. There's also `decode()` which decodes the next instruction,
// `decodeInstructions(count)` which decodes `count` instructions and `decodeOut(instruction)`
// which overwrites an existing instruction.
const instructions = decoder.decodeAll();
// Create a nasm formatter. It supports: Masm, Nasm, Gas (AT&T) and Intel (XED).
// There's also `FastFormatter` which uses less code (smaller wasm files).
// const formatter = new FastFormatter();
const formatter = new Formatter(FormatterSyntax.Nasm);
// Change some options, there are many more
formatter.digitSeparator = "`";
formatter.firstOperandCharIndex = 10;
// Format the instructions
instructions.forEach(instruction => {
const disasm = formatter.format(instruction);
// Eg. "00007FFAC46ACDB2 488DAC2400FFFFFF lea rbp,[rsp-100h]"
let line = ("0000000" + instruction.ipHi.toString(16)).substr(-8).toUpperCase() +
("0000000" + instruction.ipLo.toString(16)).substr(-8).toUpperCase();
line += " ";
const startIndex = instruction.ipLo - exampleRipLo;
exampleCode.slice(startIndex, startIndex + instruction.length).forEach(b => {
line += ("0" + b.toString(16)).substr(-2).toUpperCase();
});
for (let i = instruction.length; i < hexBytesColumnByteLength; i++)
line += " ";
line += " ";
line += disasm;
console.log(line);
});
我正在学习 Assembly 作为一名 web 开发人员(因此修补反汇编程序 Node.js 库)并阅读 Intel x86 Architecture Developer Manual 但不知何故我不认识变量的术语或目的/含义此处使用:
const exampleRipLo = 0xC46ACDA4;
const exampleRipHi = 0x00007FFA;
它们代表什么,我应该如何决定使用哪些值?
RIP 是 x86-64 上的 64 位程序计数器。反汇编程序使用 RIP 来跟踪每条指令的地址。
exampleRip
是exampleCode
的起始地址,显示为每条指令的地址。
通常你会为此使用一个 64 位整数变量,但 JavaScript 数字是 IEEE double
浮点数,因此它们将大数字舍入为 2 的某个幂的倍数,即舍去大数的低位,使其无法用于内核地址(在规范地址范围的高半部分)。 (awk也用了double
,unix.SE上的https://unix.stackexchange.com/questions/649013/why-does-awk-print-0xffffffffbb6002e0-as-ffffffffbb600000-using-printf就是效果的例子,有FP解释。)
这就是这条评论的重点:
// You have to enable the bigint feature to get i64/u64 APIs, not all browsers support BigInt
他们解释说他们没有使用 BigInt 功能,因此他们使用两个变量(exampleRipHi 和 exampleRipLo)来实现一个 64 位变量。
const exampleRipLo = 0xC46ACDA4;
const exampleRipHi = 0x00007FFA;
那是uint64_t exampleRip = 0x00007FFAC46ACDA4
的JS版本
// iced-x86 features needed: --features "decoder nasm"
const { Decoder, DecoderOptions, Formatter, FormatterSyntax } = require("iced-x86");
/*
This code produces the following output:
00007FFAC46ACDA4 48895C2410 mov [rsp+10h],rbx
00007FFAC46ACDA9 4889742418 mov [rsp+18h],rsi
00007FFAC46ACDAE 55 push rbp
00007FFAC46ACDAF 57 push rdi
00007FFAC46ACDB0 4156 push r14
00007FFAC46ACDB2 488DAC2400FFFFFF lea rbp,[rsp-100h]
00007FFAC46ACDBA 4881EC00020000 sub rsp,200h
00007FFAC46ACDC1 488B0518570A00 mov rax,[rel 7FFA`C475`24E0h]
00007FFAC46ACDC8 4833C4 xor rax,rsp
00007FFAC46ACDCB 488985F0000000 mov [rbp+0F0h],rax
00007FFAC46ACDD2 4C8B052F240A00 mov r8,[rel 7FFA`C474`F208h]
00007FFAC46ACDD9 488D05787C0400 lea rax,[rel 7FFA`C46F`4A58h]
00007FFAC46ACDE0 33FF xor edi,edi
*/
const exampleBitness = 64;
const exampleRipLo = 0xC46ACDA4;
const exampleRipHi = 0x00007FFA;
const exampleCode = new Uint8Array([
0x48, 0x89, 0x5C, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x55, 0x57, 0x41, 0x56, 0x48, 0x8D,
0xAC, 0x24, 0x00, 0xFF, 0xFF, 0xFF, 0x48, 0x81, 0xEC, 0x00, 0x02, 0x00, 0x00, 0x48, 0x8B, 0x05,
0x18, 0x57, 0x0A, 0x00, 0x48, 0x33, 0xC4, 0x48, 0x89, 0x85, 0xF0, 0x00, 0x00, 0x00, 0x4C, 0x8B,
0x05, 0x2F, 0x24, 0x0A, 0x00, 0x48, 0x8D, 0x05, 0x78, 0x7C, 0x04, 0x00, 0x33, 0xFF
]);
const hexBytesColumnByteLength = 10;
const decoder = new Decoder(exampleBitness, exampleCode, DecoderOptions.None);
// You have to enable the bigint feature to get i64/u64 APIs, not all browsers support BigInt
decoder.ipLo = exampleRipLo;
decoder.ipHi = exampleRipHi;
// This decodes all bytes. There's also `decode()` which decodes the next instruction,
// `decodeInstructions(count)` which decodes `count` instructions and `decodeOut(instruction)`
// which overwrites an existing instruction.
const instructions = decoder.decodeAll();
// Create a nasm formatter. It supports: Masm, Nasm, Gas (AT&T) and Intel (XED).
// There's also `FastFormatter` which uses less code (smaller wasm files).
// const formatter = new FastFormatter();
const formatter = new Formatter(FormatterSyntax.Nasm);
// Change some options, there are many more
formatter.digitSeparator = "`";
formatter.firstOperandCharIndex = 10;
// Format the instructions
instructions.forEach(instruction => {
const disasm = formatter.format(instruction);
// Eg. "00007FFAC46ACDB2 488DAC2400FFFFFF lea rbp,[rsp-100h]"
let line = ("0000000" + instruction.ipHi.toString(16)).substr(-8).toUpperCase() +
("0000000" + instruction.ipLo.toString(16)).substr(-8).toUpperCase();
line += " ";
const startIndex = instruction.ipLo - exampleRipLo;
exampleCode.slice(startIndex, startIndex + instruction.length).forEach(b => {
line += ("0" + b.toString(16)).substr(-2).toUpperCase();
});
for (let i = instruction.length; i < hexBytesColumnByteLength; i++)
line += " ";
line += " ";
line += disasm;
console.log(line);
});
我正在学习 Assembly 作为一名 web 开发人员(因此修补反汇编程序 Node.js 库)并阅读 Intel x86 Architecture Developer Manual 但不知何故我不认识变量的术语或目的/含义此处使用:
const exampleRipLo = 0xC46ACDA4;
const exampleRipHi = 0x00007FFA;
它们代表什么,我应该如何决定使用哪些值?
RIP 是 x86-64 上的 64 位程序计数器。反汇编程序使用 RIP 来跟踪每条指令的地址。
exampleRip
是exampleCode
的起始地址,显示为每条指令的地址。
通常你会为此使用一个 64 位整数变量,但 JavaScript 数字是 IEEE double
浮点数,因此它们将大数字舍入为 2 的某个幂的倍数,即舍去大数的低位,使其无法用于内核地址(在规范地址范围的高半部分)。 (awk也用了double
,unix.SE上的https://unix.stackexchange.com/questions/649013/why-does-awk-print-0xffffffffbb6002e0-as-ffffffffbb600000-using-printf就是效果的例子,有FP解释。)
这就是这条评论的重点:
// You have to enable the bigint feature to get i64/u64 APIs, not all browsers support BigInt
他们解释说他们没有使用 BigInt 功能,因此他们使用两个变量(exampleRipHi 和 exampleRipLo)来实现一个 64 位变量。
const exampleRipLo = 0xC46ACDA4;
const exampleRipHi = 0x00007FFA;
那是uint64_t exampleRip = 0x00007FFAC46ACDA4