寻找一种以 C 结构作为输入并输出尺寸最小的结构的工具。
例如,给定一个只有 3 个成员的初始结构。
struct Book {
char title[50];
char author[25];
int book_id;
};
Run Code Online (Sandbox Code Playgroud)
有6种排列
struct Book1 {
char title[50];
char author[25];
int book_id;
};
struct Book2 {
char title[50];
int book_id;
char author[25];
};
struct Book3 {
char author[25];
char title[50];
int book_id;
};
struct Book4 {
char author[25];
int book_id;
char title[50];
};
struct Book5 {
int book_id;
char author[25];
char title[50];
};
struct Book6 {
int book_id;
char title[50];
char author[25];
};
Run Code Online (Sandbox Code Playgroud)
输出显示 80 …
使用这个单一 externdef 关键字创建了一个包含文件
编号.inc
EXTERNDEF MyByteArray:BYTE
Run Code Online (Sandbox Code Playgroud)
创建了一个定义 10 字节数组并包含 num.inc 的汇编文件
数字asm
option casemap:none
include num.inc
.data?
MyByteArray BYTE 10 DUP (?)
end
Run Code Online (Sandbox Code Playgroud)
创建了一个打印 MyByteArray 大小的汇编文件
ABS.ASM
option casemap:none
include num.inc
extrn printf:proc
.data
szArray db 'MyByteArray = %d',0ah,0
.code
main proc
mov rax, SIZEOF MyByteArray
mov rdx,rax
mov rcx,offset szArray
sub rsp,20h
call printf
add rsp,20h
ret
main endp
end
Run Code Online (Sandbox Code Playgroud)
上面的文件使用下面的这些命令进行组装和链接
绝对值蝙蝠
@echo on
if not defined DevEnvDir (
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Auxiliary\Build\vcvars64.bat"
)
ml64.exe abs.asm num.asm …Run Code Online (Sandbox Code Playgroud) 最近遇到了SERIALIZE指令。
串行化指令执行。在获取并执行下一条指令之前,SERIALIZE 指令可确保完成先前指令对标志、寄存器和内存的所有修改,从而耗尽对内存的所有缓冲写入。
这是一个示例 masm64 程序,其扩展名为Secret Key. 在访问密钥之前,它会通过调用包围敏感代码,SERIALIZE以期防止任何类型的推测执行。
option casemap:none
includelib kernel32.lib
includelib libcmt.lib
.data
sensitiveData db "My Secret Key", 0
.code
main proc
SERIALIZE
lea eax, [sensitiveData]
SERIALIZE
ret
main endp
end
Run Code Online (Sandbox Code Playgroud)
问题
可以SERIALIZE用来缓解推测执行漏洞,例如Meltdown吗?
更新
刚刚发现这篇文章解释了这个新指令。
Linux 内核准备使用英特尔的新 SERIALIZE 指令
...英特尔 Linux 工程师发送了一系列补丁,以在内核的sync_core() 函数中使用英特尔 SERIALIZE 指令。Linux 的sync_core 函数被调用来停止推测执行和预取修改后的代码。...
下面的代码输出
rm-data;
Content-Disposition: form-data;
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/h5z89qv6f
#include <iostream>
#include <string>
int main()
{
std::string a = "Content-Disposition: form-data;" + '\r' + '\n';
std::cout << a << std::endl;
std::string b = "Content-Disposition: " + std::string("form-data;") + '\r' + '\n';
std::cout << b << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我期望a有一个 CRLF 连接,但看起来它通过添加\r (13) + \n (10) = 23文本内起始偏移量的 ASCII 值来进行指针算术。
但是,对于b,CRLF 已正确连接。
也许更好的方法是
std::string a = "Content-Disposition: form-data;" + std::string("\r\n");
Run Code Online (Sandbox Code Playgroud)
或者
std::string a = "Content-Disposition: form-data;\r\n";
Run Code Online (Sandbox Code Playgroud)
问题
CRLF 之前的数据类型是否决定串联规则?
读完这个问题后为什么 %cl 是 sal 操作接受作为参数的唯一寄存器?,我很好奇还有哪些指令需要计数寄存器?
\n循环控制
\nLOOP 指令假定 CX、ECX 或 RCX 寄存器包含循环计数。
\nloop\nloopnz\nloopne\nloopz\nloope\nRun Code Online (Sandbox Code Playgroud)\n跳跃
\n如果 CX、ECX 或 RCX 寄存器为零,则执行跳转的跳转指令。
\njcxz\njecxz\njrcxz\nRun Code Online (Sandbox Code Playgroud)\n重复前缀
\n这些重复前缀与字符串指令一起使用并使用计数寄存器。
\nrep\nrepe\nrepz\nrepne\nrepnz\nRun Code Online (Sandbox Code Playgroud)\n位移位
\n逻辑、移位、循环和位指令(省略了双字和四字变体,例如 shld、shlq...)
\nshl\nshr\nsal\nsar\nrol\nror\nrcl\nrcr\nRun Code Online (Sandbox Code Playgroud)\nFastcall 调用约定
\n参数列表中从左到右找到的前两个 DWORD 或更小的参数被传入ECXEDX 寄存器;所有其他参数都在堆栈上从右向左传递。
__attribute__((fastcall)) void printnums(int num1, int num2, int num3){\n printf("The numbers you sent are: %d %d %d", num1, num2, num3);\n}\n\nint main(){\n printnums(1, 2, 3);\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\nMicrosoft x64 …
问题
有没有办法使用某种数组将许多参数传递给下面的 MyPrint() ,该数组包含指向 va_start() 在调用vsnprintf()之前理解的字符串的指针列表?
格式字符串说明符的示例。最好创建一个相应值的数组并将其传递给 MyPrint(),而不是单独传递每个参数。我不知道va_start()是否可以理解它。:(
"[0x%llX][%u] %s --- A=%llu (0x%llX) B=%llu (0x%llX) C=%llu (0x%llX) X=%llu (0x%llX) Y=%llu (0x%llX) Z=%llu (0x%llX)"
Run Code Online (Sandbox Code Playgroud)
细节
MyPrint() 调用vsnprintf(),后者将格式化的参数列表打印到字符数组。vsnprintf() 的声明如下所示:
int vsnprintf(char *arr, size_t len, const wchar_t *format, va_list args);
Run Code Online (Sandbox Code Playgroud)
参数
#include <stdio.h>
#include <stdarg.h>
int MyPrint(char* buffer, int bufferSize, const char *format, ...)
{
int len = 0;
va_list arguments;
va_start(arguments, format);
len = vsnprintf(buffer, bufferSize, format, arguments);
va_end(arguments); …Run Code Online (Sandbox Code Playgroud) 此示例https://godbolt.org/z/EKvvEKa6T使用此语法调用 MyFun()
(*((int(**)(void))CallMyFun))();
Run Code Online (Sandbox Code Playgroud)
是否有该模糊语法的 C 细分来解释其工作原理?
#include <stdio.h>
int MyFun(void)
{
printf("Hello, World!");
return 0;
}
void *funarray[] = { NULL,NULL,&MyFun,NULL,NULL };
int main(void)
{
size_t CallMyFun = (size_t)&funarray + (2 * sizeof(funarray[0]));
return (*((int(**)(void))CallMyFun))();
}
Run Code Online (Sandbox Code Playgroud) 目前正在使用 GCC 查看 C/C++ 中的原子操作,发现内存中自然对齐的全局变量具有原子读取和写入。
然而,我试图按位与一个全局变量,并注意到它归结为一个读取-修改-写入序列,如果有多个线程对该字节值进行操作,那么这会很麻烦。
经过一番研究,我选择了这两个例子:
C 示例- GCC 扩展__sync_fetch_and_and
#include <stdio.h>
#include <stdint.h>
uint8_t byteC = 0xFF;
int main() {
__sync_fetch_and_and(&byteC, 0xF0);
printf("Value of byteC: 0x%X\n", byteC);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
C++ 示例- 使用原子的 C++11fetch_and
#include <iostream>
#include <atomic>
std::atomic<uint8_t> byteCpp(0xFF);
int main() {
byteCpp.fetch_and(0xF0);
std::cout << "Value of byteCpp: 0x" << std::hex << static_cast<int>(byteCpp.load()) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
其他示例如下,但它们似乎不太直观且计算成本更高。
用一个pthread_mutex_lock
uint8_t byte = 0xFF;
pthread_mutex_t byte_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&byte_mutex);
byte …Run Code Online (Sandbox Code Playgroud) 尝试使用 C++11 std::uniform_int_distribution生成[2,2147483647] 范围内的随机素数p。
有人评论说这种方法可能不正确:
这个p均匀分布在所有素数 <= 2^31 - 1 的集合上并不是立即显而易见的。无论均匀性和偏差保证随机数生成器具有什么,它们都指范围内的所有整数,但代码是“筛分”只是从中取出素数。
然而,从另一篇类似的SO文章中,它指出
只要输入的随机数在该范围内均匀分布,则该方法选择的素数也将均匀分布在该范围内的素数中。
问题
这段代码真的能正确生成随机素数吗?
https://onlinegdb.com/FMzz78LBq
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <time.h>
#include <random>
int isPrimeNumber (int num)
{
if (num == 1) return 0;
for (int i = 2; i <= sqrt (num); i++)
{
if (num % i == 0)
{
// not prime
return 0;
}
}
// prime
return 1;
}
int main ()
{
std::random_device rd;
std::mt19937 …Run Code Online (Sandbox Code Playgroud)