我一直在通过反汇编一些C代码来学习汇编语言.当我用GDB反汇编这个基本的C代码时:
#include <stdio.h>
void main(void) {
printf("Hello World\n");
}
Run Code Online (Sandbox Code Playgroud)
在汇编代码中,它给出了这一行:
0x08048424 <+25>: call 0x80482e0 <puts@plt>
Run Code Online (Sandbox Code Playgroud)
但是,当我在printf函数中具有整数的代码下面进行反汇编时:
#include <stdio.h>
void main(void) {
int a = 1;
printf("Hello Word %d\n", a);
}
Run Code Online (Sandbox Code Playgroud)
它给出了这一行:
0x0804842e <+35>: call 0x80482e0 <printf@plt>
Run Code Online (Sandbox Code Playgroud)
printf @ plt和puts @ plt有什么区别?
为什么反汇编程序在没有整数参数的情况下无法识别printf函数?
我已阅读所有关于这些问题,但我还没有找到之间的差异的解释%[^\n]s,并%[^\n]在scanf()功能。
strtoull("-1", NULL, 0)在我测试的系统(带有Apple Libc的OS / X,带有Glibc的Linux)上的计算结果为18446744073709551615,(0xFFFFFFFFFFFFFFFF又名ULLONG_MAX)。
由于strtoull应该检查返回值范围之外的值,为什么它不0为所有负值返回?
编辑:周围的行为-ULLONG_MAX似乎也不一致:
strtoul("-18446744073709551615", NULL, 0) -> 1, errno=0
strtoul("-18446744073709551616", NULL, 0) -> 18446744073709551615, errno=34
Run Code Online (Sandbox Code Playgroud) 我以为C中的整数首先存储了最高有效位,例如,数字5将是0...0101。我以为我可以通过强制C让我假装一个特定的内存地址是an,int然后像在那儿一样添加到这些位来操纵特定位int。
我试图在内存中设置0的0位,然后尝试将其添加255到不同的内存地址中,这似乎工作得好像最低有效位先于最高有效位存储在内存中,因为当我在内存地址中添加1并更改时我那里的位数更大,而不是较小。如果最高有效位较早地存储在内存中,那么将255高8位是next的开头,那么将其添加到比原地址高1个字节的内存地址根本不会影响该地址int。我想知道我是否正确地解释了这一点,并且整数首先以最低有效位存储。
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
int main() {
int *x = malloc(8); //getting 4 memory addresses
int *y = malloc(8);
int *z = malloc(8);
int *a = malloc(8);
x[0] = 0; //setting 64 bits past memory addresses to 0s
x[1] = 0;
y[0] = 0;
y[1] = 0;
z[0] = 0;
z[1] = 0;
a[0] = 0;
a[1] = 0;
*((int*)((int)x)) = 255; …Run Code Online (Sandbox Code Playgroud) 我想计算a b mod c where a,b并且c是整数值。有没有一种有效的方法来做到这一点?
pow(a, b) % c 似乎不起作用。
所以让我们说:
int n = 50;
int *p = &n;
Run Code Online (Sandbox Code Playgroud)
为什么我们在 C 中使用*而不是&?*和之间的主要区别是&什么?
您能否解释以下输出:
main()
{
char f[] = "qwertyuiopasd";
printf("%s\n", f + f[6] - f[8]);
printf("%s", f + f[4] - f[8]);
}
Run Code Online (Sandbox Code Playgroud)
输出:
uiopasd
yuiopasd
Run Code Online (Sandbox Code Playgroud)
例如关于第一个printf:
f[8] 应该代表字符 'o'
f[6] 应该代表字符 'u'
%s格式打印字符串(printf("%s", f)正在给出整个"qwertyuiopasd")
那么它是如何组合在一起的,这里的字节操作是什么?
确保仅定义两个名称之一的最简单方法是什么,例如:
#define USE_OPTION1
#define USE_OPTION2
#if not(USE_OPTION1 ^ USE_OPTION2)
#error "You must use at least one option, but not both"
#endif
Run Code Online (Sandbox Code Playgroud)
我知道 C 或 C++ 中没有逻辑异或,那么最好的方法是什么?不一定是这样,是吗:
#define USE_OPTION1
#define USE_OPTION2
#ifdef USE_OPTION1
#ifdef USE_OPTION2
#error "You can't use both"
#endif
#endif
#ifdef USE_OPTION2
#ifdef USE_OPTION1
#error "You can't use both"
#endif
#endif
#ifndef USE_OPTION1
#ifndef USE_OPTION2
#error "You must use at least one"
#endif
#endif
Run Code Online (Sandbox Code Playgroud) 所以这个程序的目标基本上是在终端(通过argv[])中获取一个 26 个字母的“键”,并使用它的索引作为替代指南。因此,您在终端中输入了 2 个输入,一个在 the 中argv[],一个只是普通get_string()输入。该argv[]输入将是这样的:./s YTNSHKVEFXRBAUQZCLWDMIPGJO这里s是文件名。然后get_string()输入如下所示:plaintext: HELLO。(输入是HELLO)。然后程序将循环遍历纯文本输入中的所有字母,并根据键的索引替换其字母索引argv[]。例如,H有一个按字母顺序排列的索引7(其中a= 0 和z= 25),因此我们查看键中的第 7 个索引YTNSHKV(E)FXRBAUQZCLWDMIPGJO,在本例中为E. 它对输入中的每个字母执行此操作,我们将得到输出ciphertext: EHBBQ。这是它在终端中的样子:
./s YTNSHKVEFXRBAUQZCLWDMIPGJO
plaintext: HELLO
ciphertext: EHBBQ
Run Code Online (Sandbox Code Playgroud)
但是我的输出是EHBB,因为当我使用toupper().
而且,大小写取决于明文输入,如果明文输入是hello, world,argv[]键是YTNSHKVEFXRBAUQZCLWDMIPGJO,则输出是jrssb, ybwsp,如果输入HellO, world具有相同的键,则输出是JrssB, ybwsp。
我基本上已经解决了这个问题,我的程序根据通过命令行输入的密钥将给出的明文替换为正确的密文。现在,假设明文输入是HELLO …
我刚刚了解了 C 中的流缓冲。据我了解,printf()C 中是缓冲的,并且仅在遇到新行、缓冲区已满或我们stdout手动刷新时才打印。然后我尝试这些代码行:
#include <stdio.h>
int main() {
printf("Hello world");
while(1);
}
Run Code Online (Sandbox Code Playgroud)
理论上,控制台不会收到任何内容,因为Hello world仍在缓冲区中。但由于某些原因,我的控制台仍然显示该字符串。为什么会这样呢?
编辑:我在 Windows 10 中使用命令提示符。