小编ven*_*ngy的帖子

有什么工具可以优化 C 中的结构大小吗?

寻找一种以 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 …

c optimization

5
推荐指数
1
解决办法
444
查看次数

为什么使用 EXTERNDEF MyByteArray:BYTE 时 MASM 关键字 SIZEOF MyByteArray 始终返回 1

使用这个单一 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)

x86 assembly masm

5
推荐指数
1
解决办法
101
查看次数

SERIALIZE 指令是否会阻止推测执行?

最近遇到了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 函数被调用来停止推测执行和预取修改后的代码。...

x86 assembly cpu-architecture speculative-execution

5
推荐指数
0
解决办法
82
查看次数

将 CRLF(回车、换行)连接到 std::string 的规则

下面的代码输出

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 之前的数据类型是否决定串联规则?

c++ stdstring string-literals

3
推荐指数
1
解决办法
194
查看次数

哪些汇编指令或场景明确要求使用 RCX、ECX、CX 或 CL 计数器寄存器?

读完这个问题后为什么 %cl 是 sal 操作接受作为参数的唯一寄存器?,我很好奇还有哪些指令需要计数寄存器?

\n

循环控制

\n

LOOP 指令假定 CX、ECX 或 RCX 寄存器包含循环计数。

\n
loop\nloopnz\nloopne\nloopz\nloope\n
Run Code Online (Sandbox Code Playgroud)\n

跳跃

\n

如果 CX、ECX 或 RCX 寄存器为零,则执行跳转的跳转指令。

\n
jcxz\njecxz\njrcxz\n
Run Code Online (Sandbox Code Playgroud)\n

重复前缀

\n

这些重复前缀与字符串指令一起使用并使用计数寄存器。

\n
rep\nrepe\nrepz\nrepne\nrepnz\n
Run Code Online (Sandbox Code Playgroud)\n

位移位

\n

逻辑、移位、循环和位指令(省略了双字和四字变体,例如 shld、shlq...)

\n
shl\nshr\nsal\nsar\nrol\nror\nrcl\nrcr\n
Run Code Online (Sandbox Code Playgroud)\n

Fastcall 调用约定

\n

参数列表中从左到右找到的前两个 DWORD 或更小的参数被传入ECXEDX 寄存器;所有其他参数都在堆栈上从右向左传递。

\n
__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}\n
Run Code Online (Sandbox Code Playgroud)\n

Microsoft x64 …

assembly x86-64 masm nasm calling-convention

3
推荐指数
1
解决办法
109
查看次数

在 C 中,如何在调用 vsnprintf() 之前将可变数量的参数(例如 50+)传递给 va_start() 理解的函数?

问题

有没有办法使用某种数组将许多参数传递给下面的 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)

参数

  • arr:指向要打印输出的字符数组的指针
  • len:可以写入数组的最大字符数
  • format:打印输出的格式
  • args:指向要打印的参数列表的指针

演示

#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)

c linux

1
推荐指数
1
解决办法
110
查看次数

如何解释从函数指针数组调用 C 函数?

此示例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)

c

1
推荐指数
1
解决办法
130
查看次数

在 C/C++ 中原子按位与字节的最佳方法?

目前正在使用 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 c++ atomic stdatomic

1
推荐指数
1
解决办法
246
查看次数

使用 c++11 std::uniform_int_distribution 生成随机素数

尝试使用 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)

c++ primes

0
推荐指数
1
解决办法
169
查看次数