Address 00B6F5F0 contains the address of a pointer (0429C3B0 which is dynamic and will change on next program startup and that is why I need to use static 00B6F5F0 instead). I need to compare that pointer plus a 530 offset to value 0 which is a 4 byte int.
Pseudo code:
00B6F5F0 -> 0429C3B0 (dynamic address will change next time)
0429C3B0 + 530 = 0429C8E0
Is 0429C8E0 equal to 0?
The following assembly simply adds the offset to 00B6F5F0, which is not what I want. How can I add the offset to the pointer 0429C3B0?
cmp [00B6F5F0+00000530],0 <--- (incorrect!)
Related
I'm trying to manually walk the paging structures in order to convert a virtual address into its physical address. I have a question about the physical base address fields stored in the PML4E, PDPE, PDE, and PTE. The page size on my system is 4KB. I'm doing this on Windows in kernel mode.
As the amd64 manual says, bits 51-12 of cr3 contain the physical base address of the PML4. However, it says that bits 11-0 should be assumed as 0. I was wondering if the same thing applies to the base address fields of the other paging structures, because the diagrams that describe the translation process says 52, however the actual size is just 40 (bits 51-12).
Sample of how I'm doing the translation in C:
// clear out everything except base address field
ULONG_PTR pPml4 = __readcr3() & ~0xFFF0000000000FFF,
dataEntry;
copyAddress.PhysicalAddress.QuadPart = pPml4 + (sourceAddress.Hard.PageMapLevel4Index * 8);
if (MmCopyMemory(&dataEntry, copyAddress, 8, MM_COPY_MEMORY_PHYSICAL, &trans) != STATUS_SUCCESS) {
...
}
// dataEntry now has correct PML4E
// clear out everything except base address field
dataEntry &= ~0xFFF0000000000FFF;
// do I skip this?
dataEntry >>= 12;
From section 5.4 of the manual:
Translation-Table Base Address Field. The translation-table base-address field points to the
physical base address of the next-lower-level table in the page-translation hierarchy. Page datastructure
tables are always aligned on 4-Kbyte boundaries, so only the address bits above bit 11 are
stored in the translation-table base-address field. Bits 11:0 are assumed to be 0. The size of the field
depends on the mode...
So yes, the low 12 bits are 0 to make a 52-bit physical address.
I am trying to analyze a byte code consisting of a store instruction with inttoptr. I am having trouble to detect whether a store instruction has the inttoptr value as the value operand (3rd instruction in the following code in entry BB). My opcode looks like the following:
define dso_local i32 #test(i32* %p) #0 {
entry:
%p.addr = alloca i32*, align 8
store i32* %p, i32** %p.addr, align 8
store i32* inttoptr (i64 1000 to i32*), i32** %p.addr, align 8
%0 = load i32*, i32** %p.addr, align 8
%1 = load i32, i32* %0, align 4
ret i32 %1
}
I am trying to analyze the store instruction and trying to find whether inttoptr is in a store instruction by using classof method and with dyn_cast like the following code:
StoreInst *store = dyn_cast<StoreInst>(I);
Value *vv = store->getValueOperand();
Value *vp = store->getPointerOperand();
if(IntToPtrInst::classof(vv)){
outs() << "Inttoptr found\n";
}
if(Instruction *inp = dyn_cast<IntToPtrInst>(vv)){
outs() << "Inttoptr found\n";
}
It seems I am not being able to detect inttoptr with any of the methods. I know the byte code is not creating a separate instruction for the inttoptr but it is merging with the store instruction. It would be really nice if anyone points me what I am missing and how I can detect the inttoptr in a store instruction.
The cast you're interested in is not an instruction, but rather a constant cast from the constant integer 1000 to a pointer. You can detect it using a test like isa<ConstantExpr>(foo->getPointerOperand()) && cast<ConstantExpr>(foo->getPointerOperand())->getOpcode() == ConstantExpr::IntToPtrCast, but I typed that from memory and I'm sure there are typos.
When you read IR, instructions are always on their own line, while constants are inline as arguments or initialisers, even the quite complex constants produced using ConstantExpr.
What happened ?
var n interface{} = 2
var pn = &n
var pf = (*int64)(unsafe.Pointer(pn))
fmt.Println(pf)
fmt.Println(pn)
fmt.Println(*pn) // 2
fmt.Println(*pf) // not 2
*pf = 9
fmt.Println(*pn) //error invalid memory address or nil pointer dereference
fmt.Println(*pf) // 9
My question is Why is *pf not equal to *pn and error ?
Thanks for your reply.
n is of an interface{} type, so in memory it is represented by a struct of 2 values: a type and data. The type comes first. So you dereference it and interpret as a number.
*pf = 9 breaks that structure, so next time you try to dereference it - the runtime fails.
For simplicity let’s think we have 64-bit machine.
n is pair of 2 words of 64-bit: first is a pointer to a variable, second is a pointer to information about type - so called itab.
When you get a value pointed by pn compiler knows you want value of an interface, so it goes by the first pointer and returns int value. Compiler thinks pf is a pointer to float64 . So it lets. You to overwrite first word in the interface n with some likely incorrect address (equal to binary value of 9.0). Next time you see the value in the interface compiler uses incorrect address. And return some garbage or even SegFault.
That’s why it’s called unsafe.Pointer and is not recommended to use. Until you have very serious concerns.
An interface value contains information about the type of the data it contains and then the actual value (or a pointer to the value). When you cast a pointer to the interface to *int64, the *int64 will point into some random data in the interface value (which today happens to be a pointer to the information about the type, but this is allowed to change, this part of the language is not covered by the compatibility guarantee). When you then overwrite that data, things break, unsafe is called unsafe for a reason.
*pf is not equal to *pn because they have different types even though they might contain the same bit pattern.
A byte addressable computer with 15-bit addresses
A cache capable of storing 2k bytes of data and blocks of 8 bytes
if the memory address is direct-mapped, How can you work out the number of bits needed for the Tag, Block and Word Offset fields?
The offset has to address all the byte-positions in a block, so you need log2(8) = 3 bits for that.
There are 2k/8 = 256 sets (each set containing only 1 block because it's direct mapped), so log2(256) = 8 bits for the index (or block, as you're calling it, but may be confusing).
Tag is the rest. 15 - 8 - 3 = 4 bits left over for the tag.
I'm just starting to learn assembly in my computer science class, and I have an assignment to round a floating-point value using a specified rounding mode. I've tried to implement this using fstcw, fldcw, and frndint. I modify the rounding control bits, round the number, and then restore the previous control bits (a requirement of the assignment).
The current outstanding problem is that the instruction fld %1 seems to load the wrong value into the st(0) floating-point register (for example, if I call the function with a value of 2.6207, the number -1.9427(...)e-29 gets loaded into the register). This may be due to a misuse of gcc's inline asm(), or something else, but I'm not sure why it happens.
Here's what I have:
double roundD (double n, RoundingMode roundingMode)
{
// control word storage (2 bytes for previous, 2 for current)
char *cw = malloc(4*sizeof(char));
char *cw2 = cw + 2;
asm("fstcw %3;" // store control word in cw
"mov %3,%4;" // copy control word into cw2
"and $0xF3FF,%4;" // zero out rounding control bits
"or %2,%4;" // put new mode into rounding control bits
"fldcw %5;" // load the modified control word
"fld %1;" // load n into st(0)
"frndint;" // round n
"fstp %0;" // load st(0) back into n
"fldcw %3;" // load the old control word from cw
: "=m" (n)
: "m" (n), "m" (roundingMode),
"m" (cw), "r" (cw2), "m" (cw2) // mov requires one argument in a register
);
free(cw);
return n;
}
I'd appreciate any pointers to what's wrong with that code, specifically relating to the fld %1 line and the asm inputs/outputs. (Of course, if you can find other problems, feel free to let me know about them as well.) I don't want anyone to do my homework for me, just point me in the right direction. Thanks!
At least one issue with your current code is it is using the single precision floating point versions of fld and fstp. If you replace them with fldl and fstpl it will probably work.
Here's what I've got. It's not tested, but hopefully would be less gnarly for you to work with. :-)
double
roundd(double n, short mode)
{
short cw, newcw;
__asm__("fstcw %w0" : "=m" (cw));
newcw = cw & 0xf3ff | mode;
__asm__("fldcw %w0" : : "m" (newcw));
__asm__("frndint" : "+t" (n));
__asm__("fldcw %w0" : : "m" (cw));
return n;
}
Although, if you're not required to use assembly to achieve your rounding mode, think about using the functions in <fenv.h> instead. :-)
As the sign changes, it means that the sign bit (which is the most significant, the first one) is not correct.
That suppose to me that the pointer %1 is wrongly aligned. If you have one byte, it can
begin on 0,1,2... but if you access two bytes, the address must be 0,2,4.... and in case
of double the address must be even dividable by 8: 0,8,16
So check if the address which you use to load the value is dividable by 8. Assembly has the align keyword to guarantee that your data is correctly aligned.