・rdtsc
=Aが64bitではrdx:eaxではなくraxになるというのは言われてみればなるほど. たまたま自分が使っていた範囲ではedxは関係が無いので気が付かなかった.
・ハロウィン
興味が無いので毎度毎度, 何を祝ってるのか調べてもすぐ忘れる. カトリックの諸聖人の日(11/1)の前夜祭.
プロテスタントが多いアメリカでは前夜祭だけ盛大にやってるらしい. やはりすぐ忘れそうだ.
#include <shlobj.h>
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "User32.lib")
#include <stdio.h>
#include <string>
int main()
{
_putenv("SYSTEMDRIVE="); // 環境変数を消す
char buf[MAX_PATH];
if (SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, buf) == S_OK) {
// Xp, 2003はOK
printf("programdata=%s\n", buf);
} else {
// Vista, 2008 server, Windows 7だと動かない
int err = GetLastError();
printf("err=%d\n", err);
return 1;
}
}
#include <stdio.h>
template<typename T>
class X {
T t_;
struct DummyClass;
template<typename S, void (S::*)() const>
struct HasMemFunc { };
template<typename S>
void dispatch(int, HasMemFunc<S, &S::func>* p = 0)
{
t_.func();
}
template<typename S>
void dispatch(DummyClass*)
{
puts("no func");
}
public:
void run()
{
dispatch<T>(0);
}
};
struct A {
};
struct B {
void func() const { puts("run func"); }
};
int main()
{
X<A> a;
a.run(); // "run func"
X<B> b;
b.run(); // "no func"
}
多少意味が変わるがVC専用でよければ__if_existsを使って
template<typename T>
struct Y {
void run()
{
__if_exists(T::func) {
T().func();
}
__if_not_exists(T::func) {
puts("no func");
}
}
};
class BackDoor : public Xbyak::CodeGenerator {
public:
BackDoor(int cmd, int param)
{
#ifdef XBYAK32
push(ebx);
push(esi);
const Xbyak::Reg32& retp = esi;
mov(retp, ptr [esp + 8 + 4]);
#else
push(rbx);
const Xbyak::Reg64& retp = r8;
#ifdef XBYAK64_WIN
mov(retp, rcx);
#else
mov(retp, rdi);
#endif
#endif
mov(eax, 0x564d5868);
mov(ebx, param);
mov(ecx, cmd);
mov(edx, 0x5658);
db(0xed); // in eax, dx
mov(ptr [retp + 0], eax);
mov(ptr [retp + 4], ebx);
mov(ptr [retp + 8], ecx);
mov(ptr [retp + 12], ecx);
#ifdef XBYAK32
pop(esi);
pop(ebx);
#else
pop(rbx);
#endif
ret();
}
#include <stdio.h>
#include <algorithm>
int main()
{
printf("min(3, 1)=%u\n", std::min<size_t>(3, 1));
printf("max(1, 3)=%u\n", std::max<size_t>(1, 3));
}
//
min(3, 1)=3
max(1, 3)=1
minとmaxが逆になってるのではなく常に第1引数の値が返る.
いくらβとは言え, こんな酷いバグがあったとは.
template<class _Ty,
class _Pr> inline
const _Ty& (min)(const _Ty& _Left, _Pr)
{ // return _Left as smallest
return (_Left);
}
よくわからんところにマッチしてるなあ.
#if 1 #elif #endifがVC9やgcc 4.3.4でコンパイルできるけどgcc 4.4でエラーになる. #if 1が真となった時点で#elifの後ろの評価をしないのが正しいならgcc 4.4が間違ってるということかな. mcppのチェックでもエラーにはならなかった. 本当に殆ど何もチェックしないのでたとえば
#if 1
#elif <html>&{this}|(what)!??
#endif
もgcc 4.4以外ではエラーにならなかった.
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.2 99.9 328 589505315 ? S 06:29 0:02 init [3] % uname -a Linux mie 2.6.31.3 #1 Sun Oct 11 01:29:43 JST 2009 i686 GNU/Linuxリブートしても変わらない. 何度やっても同じ. 589505315 = 0x23232323だから何か未初期化メモリを参照したのかなあ.
% free
total used free shared buffers cached
Mem: 1519612 246140 1273472 0 161652 47088
-/+ buffers/cache: 37400 1482212
Swap: 0 0 0
だし, 触ってて特に実害はなさそうなんだけど気持ち悪い.
int func(int a, int b, int c, int d, int e) const
{
return x_ + y_ + a + b + c + d + e;
}
相当のJIT的メンバ関数はこんな感じ(memfunc.cpp).
無理に一つのソースにまとめたからやや見にくいけど
const struct {
const Reg32e& self;
const Operand& a;
const Operand& b;
const Operand& c;
const Operand& d;
} para = {
#if defined(XBYAK64_WIN)
rcx,
edx,
r8d,
r9d,
ptr [rsp + 8 * 5],
ptr [rsp + 8 * 6],
#elif defined(XBYAK64_GCC)
rdi,
esi,
edx,
ecx,
r8d,
r9d,
#else
ecx,
ptr [esp + 4 + PARA_ADJ],
ptr [esp + 8 + PARA_ADJ],
ptr [esp + 12 + PARA_ADJ],
ptr [esp + 16 + PARA_ADJ],
ptr [esp + 20 + PARA_ADJ],
#endif
};
mov(eax, ptr [para.self]);
add(eax, ptr [para.self + 4]);
add(eax, para.a);
add(eax, para.b);
...
このあたりの部分はたいしたことないんだけど一見トリッキーな記述っぽくて面白い.
int (A::*p)(int, int) const
= (int (A::*)(int, int) const)code.getCode();
みたいにやってないのはそれが理由. class Bのメンバ関数をAのメンバ関数にキャストすることはできるのだからちょっと不思議だ.
#include <stdio.h>
#include <stdlib.h>
#include <xbyak/xbyak.h>
struct A {
int x_;
int y_;
A() : x_(3), y_(5) {}
int func(int a, int b) const { return x_ + y_ + a + b; }
};
struct Code : public Xbyak::CodeGenerator {
Code()
{
#ifdef _WIN32
const int PARA_ADJ = 0;
const int RET_ADJ = 8;
#else
mov(ecx, ptr [esp + 4]);
const int PARA_ADJ = 4;
const int RET_ADJ = 0;
#endif
mov(eax, ptr [ecx]);
add(eax, ptr [ecx + 4]);
add(eax, ptr [esp + 4 + PARA_ADJ]);
add(eax, ptr [esp + 8 + PARA_ADJ]);
ret(RET_ADJ);
}
};
int main()
{
Code code;
int (A::*p)(int, int) const = 0;
*(void**)&p = (void*)code.getCode();
for (int i = 0; i < 10; i++) {
A a;
int t1, t2, x, y;
a.x_ = rand();
a.y_ = rand();
t1 = rand();
t2 = rand();
x = a.func(t1, t2);
y = (a.*p)(t1, t2);
printf("%d, %d\n", x, y);
}
}