提交 c75ef5bb 编写于 作者: 编程进阶之路's avatar 编程进阶之路

move code to repository c_cpp_code

上级 d667909f
...@@ -824,4 +824,4 @@ ...@@ -824,4 +824,4 @@
:page 146}, :page 146},
:content {:text "[:span]", :image 1694614015805}, :content {:text "[:span]", :image 1694614015805},
:properties {:color "purple"}}], :properties {:color "purple"}}],
:extra {:page 165}} :extra {:page 164}}
#include <stdio.h>
int main() {
printf("Hello, world\n");
return 0;
}
\ No newline at end of file
/*
位操作练习题
*/
#include <stdio.h>
#include <stdlib.h>
/*
* LowBit - return value of low-order 1 bit
* Examples: LowBit(0x1F) = 0x1
* LowBit(0x300) = 0x100
* LowBit(0x0) = 0x0
*/
unsigned int LowBit(unsigned int x) {
return x & (~x + 1);
}
/*
* hexAllLetter - return 1 when all 4 hex digits are letters
* Examples: hexAllLetter(0x1234) = 0
* hexAllLetter(0x1ABF) = 0
* hexAllLetter(0xABCD) = 1
A hexadecimal number orresponding to the four binary number x3x2x1x0
Let's check whether the hexadecimal number is a letter
x3x2=00 x3x2=01 x3x2=10 x3x2=11
x1x0= 00 0 0 0 1
x1x0= 01 0 0 0 1
x1x0= 10 0 0 1 1
x1x0= 11 0 1 1 1
*/
unsigned hexAllLetter(unsigned x) {
// x3 x2 x1 x0 -> hex
// 0 0 1 0 -> hex constent 0x2
unsigned x1 = x & 0x22222222; // ...xxxx0010
// 0 1 0 0 -> hex constent 0x4 // ...xxxx0100
unsigned x2 = x & 0x44444444; // ...xxxx1000
// 1 0 0 0 -> hex constent 0x8
unsigned x3 = x & 0x88888888; // ...xxx10000
// x3 * (x1 + x2) ==> x3 & (x1 + x2)
unsigned a = (x3 >> 3) & ((x2 >> 2) | (x1 >> 1));
return a;
}
int main() {
printf("%#x\n", LowBit(0xf)); // 0xf = 1111 -> 0x1
printf("%#x, is letter %#x\n", 0xabcdefab, hexAllLetter(0xabcdefab));
printf("%#x, is letter %#x\n", 0x11111111, hexAllLetter(0x11111111));
printf("%#x, is letter %#x\n", 0xa0a0a0a0, hexAllLetter(0xa0a0a0a0));
return 0;
}
/*
查看字节序
*/
#include <stdio.h>
#include <stdbool.h>
void show_byte_order(void) {
int a = 0x1100;
char *p = (char *)&a;
if (p[0] == 0x00) {
printf("little endian\n");
} else {
printf("big endian\n");
}
}
int main() {
int a = 0x12345678;
char *p = (char *)&a;
printf("%x %x %x %x\n", p[0], p[1], p[2], p[3]); // 78 56 34 12 小端字节序
show_byte_order();
return 0;
}
\ No newline at end of file
/*
整数运算
*/
#include <stdio.h>
#include <limits.h>
int main() {
/* 无符号数加法 */
unsigned char us1 = 255; // UCHAR_MAX 2^8 - 1
unsigned char us2 = 2;
printf("us1 + us2 = %d\n", us1 + us2 - (UCHAR_MAX + 1)); /*溢出*/
/*无符号数求反*/
unsigned char us3 = 1;
printf("~us3 = %hhu\n", (UCHAR_MAX + 1)-us3);
return 0;
}
\ No newline at end of file
#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start, size_t len)
{
// start 就是传递对象的最低地址
size_t i;
for (i = 0; i < len; i++)
{
printf("%.2x ", start[i]);
}
printf("\n");
}
void show_int(int x)
{
printf("show bytes(int): ");
show_bytes((byte_pointer)&x, sizeof(int));
// (byte_pointer) &x: 表示将 &x 视为指向对象的字节序列,而不是指向源数据的指针。
}
void show_float(float x)
{
printf("show bytes(float): ");
show_bytes((byte_pointer)&x, sizeof(float));
}
void show_pointer(void *x)
{
printf("show bytes(pointer): ");
show_bytes((byte_pointer)&x, sizeof(void *));
}
void test_show_bytes(int val)
{
int ival = val;
float fval = (float)ival;
int *pval = &ival;
show_int(ival); // show bytes(int): 39 30 00 00
show_float(fval); // show bytes(float): 00 e4 40 46
show_pointer(pval); // show bytes(pointer): 8c fa df 0a 77 00 00 00
}
int main()
{
test_show_bytes(0x00003039);
return 0;
}
\ No newline at end of file
#include <stdio.h>
int main() {
int tx, ty;
unsigned ux, uy;
// tx = (int) ux;
// uy = (unsigned) ty;
// tx = ux;
// uy = ty;
int x = -1;
unsigned u = 2147483648;
printf("x = %u = %d\n", x, x); // x = 4294967295 = -1
printf("u = %u = %d\n", u, u); // u = 2147483648 = -2147483648
return 0;
}
int sum(int x, int y) {
return x + y;
}
int main() {
int val = sum(1, 2);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define unlikely(x) __builtin_expect(!!(x), 0) // 期望 !!(x) == 0 为真
uint32_t uint2float(uint32_t u)
{
// 32 个 0
if (u == 0x0000000)
{
return 0x00000000;
}
// 计算最高位为1的位置
int n = 31;
while (0 <= n && (((u >> n) & 0x1) == 0x0))
{
n = n - 1;
}
// printf("n = %d\n", n);
uint32_t f; // 尾数
uint32_t e; // 指数
// <= 0000 0000 1.111 1111 1111 1111 1111 1111 尾数刚好24位,最高位 1 隐含表示刚好能表示尾数,因此不需要舍入
// <= 0x00ffffff
if (u <= 0x00ffffff)
{
uint32_t mask = 0xffffffff >> (32 - n);
f = (u & mask) << (23 - n);
e = n + 127;
return (e << 23) | f;
}
// >= 0000 0001 0000 0000 0000 0000 0000 0000 尾数超过24位,最高位 1 隐含表示也不能完全表示尾数,因此需要舍入
// >= 0x01000000
else
{
// 扩展到64位
uint64_t a = 0;
a += u;
// GRS舍入规则
uint32_t g = (a >> (n - 23)) & 0x1; // 最后一个保留的位
uint32_t r = (a >> (n - 24)) & 0x1; // 第一个丢弃的位
uint32_t s = 0x0;
// 计算要丢弃的第一个位之后所有位的或
for (int j = 0; j < n - 24; ++j)
{
s = s | ((u >> j) & 0x1);
}
// 0 1 2 ? ... ?
// [24] [23] [22] ... [0]
a = a >> (n - 23);
if (r & (g | s) == 0x1)
{
a += 1; // f+1可能跑到了第24位
}
/* 没有溢出 */
if ((a >> 23) == 0x1)
{
// 0 1 1 ? ... ?
// [24] [23] [22] ... [0]
f = a & 0x007fffff; // 取后23位
e = n + 127; // 指数
return (e << 23) | f;
}
/* 溢出 */
else if ((a >> 23) == 0x2)
{
// 1 0 0 ... 0
// [24] [23] [22] ... [0]
e = n + 1 + 127;
return (e << 23);
}
}
// inf 默认错误
return 0x7f800000; // 0 1111 1111 000 0000 0000 0000 0000 0000
}
int main()
{
uint32_t uf;
float f;
for (uint32_t u = 0x00ffffff; u <= 0xffffffff; u += 0xf)
{
uf = uint2float(u);
f = (float)u;
if (unlikely(uf != *(uint32_t *)&f))
{
printf("fail\n");
return 0;
}
printf("u=%#x, f=%#x,uf=%#x\n", u, *(uint32_t *)&f, uf);
}
printf("pass\n");
return 0;
}
/*
加法
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
uint64_t add(uint64_t a, uint64_t b) {
return a + b;
}
int main() {
uint64_t a = 0xab;
uint64_t b = 0xac;
uint64_t c = add(a, b);
return 0;
}
#include <stdio.h>
#include "cpu.h"
int main() {
cpu_t cpu;
cpu.rax = 0x1234abcd5678ffaaU;
printf("rax: %x\n", cpu.rax);
printf("eax: %x\n", cpu.eax);
printf("ax: %x\n", cpu.ax);
printf("al: %x\n", cpu.al);
return 0;
}
\ No newline at end of file
#ifndef _CPU_H_
#define _CPU_H_
#include <stdlib.h>
#include <stdint.h>
typedef struct CPU_STRUCT
{
union
{
uint64_t rax;
uint32_t eax;
uint16_t ax;
uint8_t al;
};
union
{
uint8_t bl;
uint16_t bx;
uint32_t ebx;
uint64_t rbx;
};
union
{
uint8_t cl;
uint16_t cx;
uint32_t ecx;
uint64_t rcx;
};
union
{
uint8_t dl;
uint16_t dx;
uint32_t edx;
uint64_t rdx;
};
union
{
uint8_t sil;
uint16_t si;
uint32_t esi;
uint64_t rsi;
};
union
{
uint8_t dil;
uint16_t di;
uint32_t edi;
uint64_t rdi;
};
union
{
uint8_t bpl;
uint16_t bp;
uint32_t ebp;
uint64_t rbp;
};
union
{
uint8_t spl;
uint16_t sp;
uint32_t esp;
uint64_t rsp;
};
union
{
uint8_t r8b;
uint16_t r8w;
uint32_t r8d;
uint64_t r8;
};
union
{
uint8_t r9b;
uint16_t r9w;
uint32_t r9d;
uint64_t r9;
};
union
{
uint8_t r10b;
uint16_t r10w;
uint32_t r10d;
uint64_t r10;
};
union
{
uint8_t r11b;
uint16_t r11w;
uint32_t r11d;
uint64_t r11;
};
union
{
uint8_t r12b;
uint16_t r12w;
uint32_t r12d;
uint64_t r12;
};
union
{
uint8_t r13b;
uint16_t r13w;
uint32_t r13d;
uint64_t r13;
};
union
{
uint8_t r14b;
uint16_t r14w;
uint32_t r14d;
uint64_t r14;
};
union
{
uint8_t r15b;
uint16_t r15w;
uint32_t r15d;
uint64_t r15;
};
uint64_t rip;
} cpu_t;
#endif
/*
算术操作
*/
/*
// long arith(long x, long y, long z)
// x in %rdi, y in %rsi, z in %rdx
0000000000001119 <arith>:
1119: 48 31 f7 xor %rsi,%rdi // %rdi[t1] = x ^ y
111c: 48 8d 04 52 lea (%rdx,%rdx,2),%rax // %rax[3 * z]
1120: 48 c1 e0 04 shl $0x4,%rax // %rax[t2] = 3 * z << 4 = 48 * z
1124: 81 e7 0f 0f 0f 0f and $0xf0f0f0f,%edi // %edi[t3] = t1 & 0x0f0f0f0f
112a: 48 29 f8 sub %rdi,%rax // t4 = t2 - t3
112d: c3 ret
*/
long arith(long x, long y, long z) {
long t1 = x ^ y;
long t2 = z * 48;
long t3 = t1 & 0x0f0f0f0f;
long t4 = t2 - t3;
return t4;
}
int main() {
arith(10, 20, 30);
return 0;
}
/*
x86-64 除法
*/
/*
// void remdiv(long x, long y, long *qp, long *rp)
// x in %rdi, y in %rsi, qp in %rdx, rp in %rcx
0000000000001139 <remdiv>:
1139: 48 89 f8 mov %rdi,%rax // 移动被除数 x 的低 8 字节到 %rax
113c: 49 89 d0 mov %rdx,%r8 // 复制 qp 到 %r8
113f: 48 99 cqto // 将 %rax 的符号位扩展到 %rdx
1141: 48 f7 fe idiv %rsi // %rdx[余数]:%rax[商] <- x / y
1144: 49 89 00 mov %rax,(%r8) // *qp = 商
1147: 48 89 11 mov %rdx,(%rcx) // *rp = 余数
114a: c3 ret
*/
void remdiv(long x, long y, long *qp, long *rp) {
long q = x /y;
long r = x % y;
*qp = q;
*rp = r;
}
int main() {
long x = 0x1234567887654321;
long y = 0x1111111111111111;
long q = 0;
long r = 0;
remdiv(x, y, &q, &r);
return 0;
}
\ No newline at end of file
/*
leaq 指令:加载有效地址
leaq S, D
将有效地址S加载到目的操作数D中
有效地址:指向一个对象的指针或数组元素的
*/
/*
// long scale(long x, long y, long z);
// x in %rdi, y in %rsi, z in %rdx
0000000000001119 <scale>:
1119: 48 8d 04 b7 lea (%rdi,%rsi,4),%rax // %rax = %rdi[x] + 4 * %rsi[y]
111d: 48 8d 14 52 lea (%rdx,%rdx,2),%rdx // %rdx = %rdx[z] + 2 * %rdx[z]
1121: 48 8d 04 90 lea (%rax,%rdx,4),%rax // %rax = %rax + 4 * %rdx = %rdi[x] + 4 * %rsi[y] + 4 * (%rdx[z] + 2 * %rdx[z])
1125: c3 ret
*/
long scale(long x, long y, long z)
{
long t = x + 4 * y + 12 * z;
return t;
}
int main() {
long a = 10;
long b = 20;
long c = 30;
long d = scale(a, b, c);
return 0;
}
\ No newline at end of file
/*
移位指令
*/
/*
// long shift_left_4_rightn(long x, long n)
// x in %rdi, n in %rsi
0000000000001119 <shift_left_4_rightn>:
1119: 48 89 f8 mov %rdi,%rax
111c: 48 c1 e0 04 shl $0x4,%rax // 左移 %rax = %rax << 4
1120: 89 f1 mov %esi,%ecx // %ecx = %rsi [%rcx %ecx %cx %cl]
1122: 48 d3 f8 sar %cl,%rax // 算术右移 %rax = %rax >> %cl
1125: c3 ret
*/
long shift_left_4_rightn(long x, long n) {
x <<= 4;
x >>= n;
return x;
}
int main() {
shift_left_4_rightn(0xff, 4);
return 0;
}
\ No newline at end of file
/*
特殊的算术运算
*/
#include <inttypes.h>
typedef unsigned __int128 uint128_t;
/*
// void store_uprod(uint128_t *dest, uint128_t x, uint64_t y)
// dest in %rdi, x in %rsi, y in %rdx
0000000000001139 <store_uprod>:
1139: 48 89 f0 mov %rsi,%rax // %rax <- x
113c: 48 f7 e2 mul %rdx // %rdx(高64位):%rax(低64位) <- x * y
113f: 48 89 07 mov %rax,(%rdi) // *dest = 低64位
1142: 48 89 57 08 mov %rdx,0x8(%rdi) // *(dest + 8) = 高64位
1146: c3 ret
*/
void store_uprod(uint128_t *dest, uint64_t x, uint64_t y) {
*dest = x * (uint128_t) y;
}
int main() {
uint128_t dest;
uint64_t x = 0x1234567887654321;
uint64_t y = 0x1111111111111111;
store_uprod(&dest, x, y);
return 0;
}
\ No newline at end of file
/*
定长数组
*/
#define N 16
typedef int fix_matrix[N][N];
int fix_prod_ele(fix_matrix A, fix_matrix B, long i, long k) {
long j;
int result = 0;
for(j = 0; j < N; j++) {
result += A[i][j] * B[j][k];
}
return result;
}
/*
// int fix_prod_ele(fix_matrix A, fix_matrix B, long i, long k)
// A in %rdi, B in %rsi, i in %rdx, k in %rcx
fix_prod_ele:
salq $6, %rdx // i *= 64
addq %rdx, %rdi // &A[i][0] (A + 4 * 16 * i)
leaq (%rsi,%rcx,4), %rax // &B[0][k] (B + 4 * k)
leaq 1024(%rax), %rsi // &B[N][k] (B + 4 * k + 4 * 16 * 16)
movl $0, %ecx // result = 0
.L2:
movl (%rdi), %edx // A[i][0]
imull (%rax), %edx // A[i][0] * B[0][k]
addl %edx, %ecx // result += A[i][0] * B[0][k]
addq $4, %rdi // A[i]++
addq $64, %rax // B[0][k] + N
cmpq %rsi, %rax // compare B[0][k] + N and B[N][k]
jne .L2 // if not equal, jump to .L2
movl %ecx, %eax // return result
ret
*/
/*
条件传送
*/
/*
// long absdiff(long x, long y)
// x in %rdi, y in %rsi
absdiff:
movq %rsi, %rdx // 将 y 存储到 %rdx
subq %rdi, %rdx // %rdx = y - x
movq %rdi, %rax // 将 x 存储到 %rax
subq %rsi, %rax // %rax = x - y
cmpq %rsi, %rdi // 比较 x 和 y
cmovl %rdx, %rax // 如果 x < y, 则将 %rdx 的值传送到 %rax
ret
*/
long absdiff(long x, long y) {
long result;
if(x < y) {
result = y - x;
}
else {
result = x - y;
}
return result;
}
int main() {
absdiff(2, 3);
return 0;
}
\ No newline at end of file
/*
条件控制
*/
long lt_cnt = 0;
long ge_cnt = 0;
/*
// long absdiff_se(long x, long y)
// x in %rdi, y in %rsi
absdiff_se:
cmpq %rsi, %rdi // 比较 x 和 y
jge .L2 // 如果 x >= y, 跳转到 .L2
addq $1, lt_cnt(%rip) // lt_cnt++
movq %rsi, %rax // 将 y 存储到 %rax
subq %rdi, %rax // 计算 y - x 并存储到 %rax
ret
.L2:
addq $1, ge_cnt(%rip) // ge_cnt++
movq %rdi, %rax // 将 x 存储到 %rax
subq %rsi, %rax // 计算 x - y 并存储到 %rax
ret
*/
long absdiff_se(long x, long y) {
long result;
if (x < y) {
lt_cnt++;
result = y - x;
}
else {
ge_cnt++;
result = x - y;
}
return result;
}
int main() {
absdiff_se(2, 3);
return 0;
}
\ No newline at end of file
/*
条件传送非法示例
*/
long cread(long *xp)
{
return (xp ? *xp : 0);
}
int main() {
long a = 0;
long *xp = &a;
long result = cread(xp);
return 0;
}
// gcc -Og -S cread.c
\ No newline at end of file
/*
分析寄存器存放的程序值
*/
/*
// long dw_loop(long x)
// x in %rdi
dw_loop:
movq %rdi, %rax // 将 x 存储到 %rax
movq %rdi, %rcx // 将 x 存储到 %rcx
imulq %rdi, %rcx // 将 y=x*x 存储到 %rcx
leaq (%rdi,%rdi), %rdx // 将 n=2*x 存储到 %rdx
.L2:
leaq 1(%rcx,%rax), %rax // x += y, (*p)++
subq $1, %rdx // n--
testq %rdx, %rdx // 测试 n & n 是否为 0
jg .L2
ret
*/
long dw_loop(long x) {
long y = x * x;
long *p = &x;
long n = 2 * x;
do {
x += y;
(*p)++;
n--;
} while(n > 0);
return x;
}
int main() {
dw_loop(3);
return 0;
}
\ No newline at end of file
/*
do-while 循环
*/
/*
// long fact_do(long n)
// n in %rdi
fact_do:
movl $1, %eax // result = 1
.L2:
imulq %rdi, %rax // result *= n
subq $1, %rdi // n = n - 1
cmpq $1, %rdi // 比较 n 和 1
jg .L2 // 如果 n > 1, 则跳转到 .L2
ret
*/
long fact_do(long n) {
long result = 1;
do {
result *= n;
n = n - 1;
} while (n > 1);
return result;
}
int main() {
fact_do(3);
return 0;
}
/*
for 循环:GCC 为 for 循环产生代码是 while 循环的两种翻译方式之一
这里我们看第一种:跳转到中间
*/
/*
// gcc -Og -S fact_for.c
// long fact_for(long n)
// n in %rdi
fact_for:
movl $2, %eax // i = 2
movl $1, %edx // result = 1
jmp .L2 // 跳转到 .L2
.L3:
imulq %rax, %rdx // result *= i
addq $1, %rax // i++
.L2:
cmpq %rdi, %rax // 测试 i - n
jle .L3 // 如果 i - n <= 0, 跳转到 .L3
movq %rdx, %rax
ret
*/
long fact_for(long n)
{
long result = 1;
long i;
for (i = 2; i <= n; i++)
{
result *= i;
}
return result;
}
int main()
{
fact_for(3);
return 0;
}
/*
while 循环的第一种翻译方法
*/
/*
// gcc -Og -S fact_while.c
// long fact_while(long n)
// n in %rdi
fact_while:
movl $1, %eax // result = 1
jmp .L2 // 跳转到 .L2
.L3:
imulq %rdi, %rax // result *= n
subq $1, %rdi // n--
.L2:
cmpq $1, %rdi // 测试 n - 1 是否为 0
jg .L3 // 如果 n - 1 > 0, 跳转到 .L3
ret
*/
long fact_while(long n) {
long result = 1;
while (n > 1)
{
result *= n;
n = n - 1;
}
return result;
}
int main() {
fact_while(3);
return 0;
}
\ No newline at end of file
/*
while 循环的第二种翻译方法
*/
/*
// gcc -O1 -S fact_while.c
// long fact_while(long n)
// n in %rdi
fact_while:
cmpq $1, %rdi // 测试 n - 1 是否为 0
jle .L4 // 如果 n - 1 <= 0, 跳转到 .L4
movl $1, %eax // result = 1
.L3:
imulq %rdi, %rax // result *= n
subq $1, %rdi // n--
cmpq $1, %rdi // 测试 n - 1 是否为 0
jne .L3 // 如果 n - 1 != 0, 跳转到 .L3
ret
.L4:
movl $1, %eax // result = 1
ret
*/
long fact_while(long n) {
long result = 1;
while (n > 1)
{
result *= n;
n = n - 1;
}
return result;
}
int main() {
fact_while(3);
return 0;
}
\ No newline at end of file
/*
// long absdiff_se(long x, long y)
// x in %rdi, y in %rsi
absdiff_se:
cmpq %rsi, %rdi // 比较 x 和 y
jge .L2 // 如果 x >= y, 跳转到 .L2
addq $1, lt_cnt(%rip) // lt_cnt++
movq %rsi, %rax // 将 y 存储到 %rax
subq %rdi, %rax // 计算 y - x 并存储到 %rax
ret
.L2:
addq $1, ge_cnt(%rip) // ge_cnt++
movq %rdi, %rax // 将 x 存储到 %rax
subq %rsi, %rax // 计算 x - y 并存储到 %rax
ret
*/
long lt_cnt = 0;
long ge_cnt = 0;
long gotodiff_se(long x, long y) {
long result;
if(x >= y) {
goto x_ge_y;
}
lt_cnt++;
result = y - x;
return result;
x_ge_y:
ge_cnt++;
result = x - y;
return result;
}
int main() {
gotodiff_se(2, 3);
return 0;
}
/*
switch 语句的翻译
*/
/*
// gcc -Og -S switch_eg.c
// void switch_eg(long x, long n, long *dest)
// x in %rdi, n in %rsi, dest in %rdx
switch_eg:
subq $100, %rsi // index = n - 100
cmpq $6, %rsi // 比较 n - 100 和 6
ja .L8 // 如果 n - 100 > 6, 跳转到 .L8
leaq .L4(%rip), %rcx // 将 .L4 的地址存入 %rcx
movslq (%rcx,%rsi,4), %rax // 将 %rcx + index * 4 的值存入 %rax
addq %rcx, %rax // 将 %rcx + %rcx + index * 4 存入 %rax
jmp *%rax // 跳转到 %rax 指向的地址
.section .rodata
.align 4
.align 4
.L4:
.long .L7-.L4 // .L7 - .L4 = 0x0 case 100
.long .L8-.L4 // .L8 - .L4 = 0x4 default
.long .L6-.L4 // .L6 - .L4 = 0x8 case 102
.long .L5-.L4 // .L5 - .L4 = 0xc case 103
.long .L3-.L4 // .L3 - .L4 = 0x10 case 104
.long .L8-.L4 // .L8 - .L4 = 0x14 default
.long .L3-.L4 // .L3 - .L4 = 0x18 case 106
.text
.L7:
leaq (%rdi,%rdi,2), %rax
leaq (%rdi,%rax,4), %rdi
jmp .L2
.L6:
addq $10, %rdi
.L5:
addq $11, %rdi
.L2:
movq %rdi, (%rdx) // 将 %rdi 的值存入 %rdx 指向的地址
ret
.L3:
imulq %rdi, %rdi
jmp .L2
.L8:
movl $0, %edi
jmp .L2
*/
void switch_eg(long x, long n, long *dest) {
long val = x;
switch (n) {
case 100:
val *= 13;
break;
case 102:
val += 10;
/*Fall through*/
case 103:
val += 11;
break;
case 104:
case 106:
val *= val;
break;
default:
val = 0;
}
*dest = val;
}
int main() {
long x = 1;
long n = 100;
long *dest = &x;
switch_eg(x, n, dest);
return 0;
}
void switch_eg_impl(long x, long n, long *dest) {
/*Table of code pointers*/
static void *jt[7] = {
&&loc_A, &&loc_def,&&loc_B,
&&loc_C, &&loc_D,&&loc_def,
&&loc_D
}; // && gcc 提供的运算符,它创建一个指向代码的指针
unsigned long index = n - 100;
long val;
// 超出范围 执行 default
if(index > 6) {
goto loc_def;
}
goto *jt[index];
loc_A: /*case 100*/
val = x * 13;
goto done;
loc_B: /*case 102*/
x = x + 10;
/*Fall through*/
loc_C: /*case 103*/
val = x + 11;
goto done;
loc_D: /*case 104, 106*/
val = x * x;
loc_def: /*default*/
val = 0;
done:
*dest = val;
}
\ No newline at end of file
/*
浮点数数传送指令
*/
float float_mov(float v1, float *src, float *dst) {
float v2 = *src;
*dst = v1;
return v2;
}
/*
// float float_mov(float v1, float *src, float *dst)
// v1 in %xmm0, src in %rdi, dest in %rsi
float_mov:
movaps %xmm0, %xmm1 // xmm1 = xmm0
movss (%rdi), %xmm0 // xmm0 = *src
movss %xmm1, (%rsi) // *dst = xmm1
ret
*/
int main() {
float v1 = 1.0;
float src = 10.0;
float dst;
float v2 = float_mov(v1, &src, &dst);
return 0;
}
\ No newline at end of file
/** 将下面汇编代码转为 C 代码
xp in %rdi, yp in %rsi, zp in %rdx
movq (%rdi), %r8 |读出xp指向的内容,并写入到 %r8
movq (%rsi), %rcx |读出yp指向的内容,并写入到 %rcx
movq (%rdx), %rax |读出zp指向的内容,并写入到 %rax
movq %r8, (%rsi) |读出 %r8 的内容,写入到 yp 指向的内存中
movq %rcx, (%rdx) |读出 %rcx 的内容,写入到 zp 指向的内存中
movq %rax, (%rdi) |读出 %rax 的内容,写入到 xp 指向的内存中
ret 返回
*/
void decode1(long *xp, long *yp, long *zp) {
long x = *xp;
long y = *yp;
long z = *zp;
*yp = x;
*zp = y;
*xp = z;
}
int main() {
long a = 10;
long b = 20;
long c = 30;
decode1(&a, &b, &c);
printf("a = %ld, b = %ld, c = %ld\n", a, b, c);
return 0;
}
\ No newline at end of file
/*
mov 指令示例
*/
#include <stdio.h>
/*
// long exchange(long *xp, long y)
// xp in %rdi , y in %rsi
0000000000001149 <exchange>:
1149: 48 8b 07 mov (%rdi),%rax // 从 xp 中获取 x, 并设置返回值
114c: 48 89 37 mov %rsi,(%rdi) // 将 y 存入 xp
114f: c3 ret // 函数返回
*/
long exchange(long *xp, long y)
{
long x = *xp;
*xp = y;
return x;
}
int main() {
long a = 10;
long b = 20;
b = exchange(&a, b);
printf("a = %d, b = %d\n", a, b);
}
#include <stdio.h>
void multstore(long , long , long *);
int main() {
long d;
multstore(2,3,&d);
printf("2 * 3 ---> %ld\n", d);
return 0;
}
long mult2(long l1,long l2){
long s = l1 * l2;
return s;
}
\ No newline at end of file
long mult2(long l1,long l2);
void multstore(long x, long y, long *dest) {
long t = mult2(x, y);
*dest = t;
}
\ No newline at end of file
/*
寄存器中的局部存储空间:调用者保存寄存器和被调用者保存寄存器
*/
#include <stdio.h>
long Q(long x) {
long val = 8 * x;
return val;
}
long P(long x, long y) {
long u = Q(y);
long v = Q(x);
return u + v;
}
/*
// long Q(long x)
// x in %rdi
Q:
leaq 0(,%rdi,8), %rax
ret
// long P(long x, long y)
// x in %rdi, y in %rsi
P:
pushq %rbp // save caller's %rbp (frame pointer)
pushq %rbx // save caller's %rbx
movq %rdi, %rbp // save x in %rbp
movq %rsi, %rdi // save y in %rdi
call Q // call Q(y)
movq %rax, %rbx // save Q(y) in %rbx
movq %rbp, %rdi // restore x in %rdi
call Q // call Q(x)
addq %rbx, %rax // add Q(y) to Q(x)
popq %rbx // restore caller's %rbx
popq %rbp // restore caller's %rbp
ret
main:
subq $8, %rsp
movl $3, %esi
movl $2, %edi
call P
*/
int main() {
long x = P(2, 3);
printf("%ld\n", x);
return 0;
}
/*
转移控制
*/
#include <stdio.h>
void multstore(long, long, long *);
int main()
{
long d;
multstore(2, 3, &d);
printf("2 * 3 ---> %ld\n", d);
return 0;
}
long mult2(long l1, long l2)
{
long s = l1 * l2;
return s;
}
\ No newline at end of file
long mult2(long l1,long l2);
void multstore(long x, long y, long *dest) {
long t = mult2(x, y);
*dest = t;
}
\ No newline at end of file
/*
数据传送:寄存器可以直接传送 6 个整型参数(包括指针),其他参数通过栈传送
*/
void proc(long a1, long *a1p, int a2, int *a2p, short a3, short *a3p, char a4, char *a4p)
{
*a1p += a1;
*a2p += a2;
*a3p += a3;
*a4p += a4;
}
int main() {
long a1 = 0;
int a2 = 0;
short a3 = 0;
char a4 = 0;
proc(0x4d2l, &a1, 0x20, &a2, (short) 0xc, &a3, (char) 0x60, &a4);
return 0;
}
/*
// void proc(long a1, long *a1p, int a2, int *a2p, short a3, short *a3p, char a4, char *a4p)
// a1 in %rdi (64 bits)
// a1p in %rsi (64 bits)
// a2 in %edx (32 bits)
// a2p in %rcx (64 bits)
// a3 in %r8w (16 bits)
// a3p in %r9 (64 bits)
// a4 in %rsp + 8 (8 bits)
// a4p in %rsp + 16 (64 bits)
0000000000001139 <proc>:
1139: 48 8b 44 24 10 mov 0x10(%rsp),%rax // 读取 a4p 的值存入 %rax
113e: 48 01 3e add %rdi,(%rsi) // *a1p += a1
1141: 01 11 add %edx,(%rcx) // *a2p += a2
1143: 66 45 01 01 add %r8w,(%r9) // *a3p += a3
1147: 8b 54 24 08 mov 0x8(%rsp),%edx // 将栈中的 0x8(%rsp) 的值存入 %edx
114b: 00 10 add %dl,(%rax) // *a4p += a4
114d: c3 ret
000000000000114e <main>:
114e: 48 83 ec 28 sub $0x28,%rsp // 为栈分配 0x28 字节的空间
1152: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
1159: 00 00
115b: 48 89 44 24 18 mov %rax,0x18(%rsp)
1160: 31 c0 xor %eax,%eax // 将 %eax 置为 0:开始准备参数
1162: 48 c7 44 24 10 00 00 movq $0x0,0x10(%rsp) // a1 = 0
1169: 00 00
116b: c7 44 24 0c 00 00 00 movl $0x0,0xc(%rsp) // a2 = 0
1172: 00
1173: 66 c7 44 24 0a 00 00 movw $0x0,0xa(%rsp) // a3 = 0
117a: c6 44 24 09 00 movb $0x0,0x9(%rsp) // a4 = 0
117f: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx // 将栈中的 0xc(%rsp) 的地址存入 %rcx 第四个参数(a2p)
1184: 48 8d 74 24 10 lea 0x10(%rsp),%rsi // 将栈中的 0x10(%rsp) 的地址存入 %rsi 第二个参数(a1p)
1189: 48 8d 44 24 09 lea 0x9(%rsp),%rax // 将栈中的 0x9(%rsp) 的地址存入 %rax
118e: 50 push %rax // 将 %rax 的值存入栈中 第八个参数(a4p) %rsp = %rsp - 0x8
118f: 6a 60 push $0x60 // 将 $0x60 的值存入栈中 第七个参数(a4) %rsp = %rsp - 0x8
1191: 4c 8d 4c 24 1a lea 0x1a(%rsp),%r9 // 将栈中的 0x1a(%rsp) 的地址存入 %r9 第六个参数(a3p)
1196: 41 b8 0c 00 00 00 mov $0xc,%r8d // 第五个参数(a3)
119c: ba 20 00 00 00 mov $0x20,%edx // 第三个参数(a2)
11a1: bf d2 04 00 00 mov $0x4d2,%edi // 第一个参数(a1) 参数准备完毕
11a6: e8 8e ff ff ff call 1139 <proc> // 调用 proc 函数,将返回地址存入栈中
11ab: 48 83 c4 10 add $0x10,%rsp // 返回地址
*/
/*
高地址 栈帧 %rsp 的变化 main 指令 进入 proc 时 %rsp 位置
|---------------------------| | |
| | | |
|---------------------------| | |
| | | |
|---------------------------| | |
| | | |
|---------------------------| | |
| | | |
|---------------------------| <- %rsp + 0x18 | |
| long a1 = 0 | | |
|---------------------------| <- %rsp + 0x10 |movq $0x0,0x10(%rsp) |
| int a2 = 0 | | |
|---------------------------| <- %rsp + 0xc |movl $0x0,0xc(%rsp) |
| short a3 = 0 | | |
|---------------------------| <- %rsp + 0xa |movw $0x0,0xa(%rsp) |
| char a4 = 0 | | |
|---------------------------| <- %rsp + 0x9 |movb $0x0,0x9(%rsp) |
| | | |
|---------------------------| | |
| | | |
|---------------------------| | |
| | | |
|---------------------------| <- %rsp | |
| 0x9(%rsp) &a4 | | |
|---------------------------| <- %rsp - 0x8 | push %rax |
| 0x60 | | |
|---------------------------| <- %rsp - 0x10 | push $0x60 |
| 0x11ab | | |
|---------------------------| <- %rsp - 0x18 | call 1139 <proc> | <- %rsp
*/
\ No newline at end of file
/*
递归过程
*/
/*
rfact:
cmpq $1, %rdi // 比较 n 和 1
jg .L8 // 如果 n > 1,跳转到 .L8
movl $1, %eax // 如果 n <= 1,返回 1
ret
.L8:
pushq %rbx // 保存 callee's %rbx
movq %rdi, %rbx // 保存 n in %rbx
leaq -1(%rdi), %rdi // n = n - 1
call rfact // 调用 rfact(n-1)
imulq %rbx, %rax // result = n * rfact(n-1)
popq %rbx // 恢复 callee's %rbx
ret
*/
long rfact(long n) {
long result;
if(n <= 1) {
result = 1;
} else {
result = n * rfact(n-1);
}
return result;
}
int main() {
long result = rfact(5);
return 0;
}
/*
栈上的局部存储:有时候局部数据必须存储在内存中
1. 寄存器不足够存放所有本地数据
2. 对局部变量使用 取地址运算符&
3. 局部变量是数组或结构
*/
/*
本例中,处理取地址运算符&
*/
long swap_add(long *xp, long *yp) {
long x = *xp;
long y = *yp;
*xp = y;
*yp = x;
return x + y;
}
long caller() {
long arg1 = 534; // 0x216
long arg2 = 1057; // 0x421
long sum = swap_add(&arg1, &arg2);
long diff = arg1 - arg2;
return sum * diff;
}
/*
0000000000001139 <swap_add>:
1139: 48 8b 07 mov (%rdi),%rax
113c: 48 8b 16 mov (%rsi),%rdx
113f: 48 89 17 mov %rdx,(%rdi)
1142: 48 89 06 mov %rax,(%rsi)
1145: 48 01 d0 add %rdx,%rax
1148: c3 ret
0000000000001149 <caller>:
1149: 48 83 ec 28 sub $0x28,%rsp // 在栈上分配 0x28 = 40 字节的空间
114d: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax // 获取栈底指针
1154: 00 00
1156: 48 89 44 24 18 mov %rax,0x18(%rsp) // 保存栈底指针
115b: 31 c0 xor %eax,%eax // 将 %eax 置为 0
115d: 48 c7 44 24 08 16 02 movq $0x216,0x8(%rsp) // arg1 = 534
1164: 00 00
1166: 48 c7 44 24 10 21 04 movq $0x421,0x10(%rsp) // arg2 = 1057
116d: 00 00
116f: 48 8d 74 24 10 lea 0x10(%rsp),%rsi // &arg2
1174: 48 8d 7c 24 08 lea 0x8(%rsp),%rdi // &arg1
1179: e8 bb ff ff ff call 1139 <swap_add> // swap_add(&arg1, &arg2)
117e: 48 8b 54 24 08 mov 0x8(%rsp),%rdx //
1183: 48 2b 54 24 10 sub 0x10(%rsp),%rdx
1188: 48 0f af c2 imul %rdx,%rax
...
*/
int main() {
caller();
return 0;
}
/*
冲突不命中:计算两个向量的点积
*/
float dotprod(float x[8], float y[8]) {
float sum = 0.0;
int i;
for(i = 0; i < 8; i++) {
sum += x[i] * y[i];
}
return sum;
}
/*
局部性
*/
#include <stdio.h>
#define N 10
#define M 10
int sumvec(int v[N]) {
int i, sum = 0;
for(i = 0; i < N; i++) {
sum += v[i];
}
return sum;
}
int sumarrayrows(int a[M][N]) {
int i, j, sum = 0;
for(i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
sum += a[i][j];
}
}
return sum;
}
int sumarraycols(int a[M][N]) {
int i, j, sum = 0;
for(j = 0; j < N; j++) {
for(i = 0; i < M; i++) {
sum += a[i][j];
}
}
return sum;
}
int main() {
int v[N] = {1,2,3,4,5,6,7,8,9,10};
int sum = sumvec(v);
printf("sum = %d\n", sum);
return 0;
}
\ No newline at end of file
/* 一独占方式打开文件 */
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char *argv[]) {
int fd = open(argv[1], O_WRONLY);
if(fd != -1) {
fprintf(stdout, "[PID %ld] File \"%s\" already exists\n", (long)getpid(), argv[1]);
close(fd);
} else {
/* No such file or directory */
if(errno != ENOENT) {
perror("open: ");
exit(EXIT_FAILURE);
} else {
/* */
fd = open(argv[1], O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
if(fd == -1) {
perror("open: ");
exit(EXIT_FAILURE);
}
fprintf(stdout, "[PID %ld] File \"%s\" already exists\n", (long)getpid(), argv[1]);
}
}
return 0;
}
/* 复制文件描述符 */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* open close*/
#include <fcntl.h>
/* read write close lseek dup dup2*/
#include <unistd.h>
int main() {
int fd;
// close(2); // 关闭 文件描述符 2
// fd = dup(1); // 复制文件描述符 1
// printf("%d\n", fd); // 2
fd = dup2(2, 1);
fd = fcntl(1, F_DUPFD, 2);
dup3();
return 0;
}
/*编写一个类似于 cp 命令的程序,当使用该程序复制一个包含空洞(连续的空字节)的普通文件时,要求目标文件的空洞与源文件保持一致*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* open close*/
#include <fcntl.h>
/* read write close lseek */
#include <unistd.h>
#define BUFFER_SIZE 1
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: %s source dest\n", argv[0]);
exit(EXIT_FAILURE);
}
char *source_file = argv[1];
char *destination_file = argv[2];
int source_fd = open(source_file, O_RDONLY);
if (source_fd == -1) {
fprintf(stderr, "open: %s", strerror(errno));
exit(EXIT_FAILURE);
}
int dest_fd = open(destination_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (dest_fd == -1) {
fprintf(stderr, "open: %s", strerror(errno));
close(source_fd);
exit(EXIT_FAILURE);
}
char buffer[BUFFER_SIZE];
ssize_t bytes_read;
while ((bytes_read = read(source_fd, buffer, BUFFER_SIZE)) > 0) {
if(bytes_read == - 1) {
fprintf(stderr, "read: %s", strerror(errno));
close(source_fd);
close(dest_fd);
exit(EXIT_FAILURE);
}
/* check file hole */
if(buffer[0] == '\0') {
lseek(dest_fd, 1, SEEK_CUR);
continue;
}
ssize_t bytes_written = write(dest_fd, buffer, bytes_read);
if (bytes_written == -1) {
fprintf(stderr, "write: %s", strerror(errno));
close(source_fd);
close(dest_fd);
exit(EXIT_FAILURE);
}
}
if (bytes_read == -1) {
fprintf(stderr, "read: %s", strerror(errno));
close(source_fd);
close(dest_fd);
exit(EXIT_FAILURE);
}
close(source_fd);
close(dest_fd);
fprintf(stdout, "copy file from %s to %s finished\n", source_file, destination_file);
return 0;
}
/* 文件控制操作 */
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main() {
int flag, access_mode;
int fd = open("test.txt", O_RDONLY | O_SYNC);
flag = fcntl(fd, F_GETFL); /* 第三个参数不需要 */
/* 测试文件是否以同步方式打开 */
if(flag & O_SYNC) {
fprintf(stdout, "SYNC\n");
}
/* 判断文件是否可读 */
access_mode = flag & O_ACCMODE;
if(access_mode == O_RDONLY || access_mode == O_RDWR) {
fprintf(stdout, "READ\n");
}
/*添加 O_APPEND 标志 */
flag |= O_APPEND;
if(fcntl(fd, F_SETFL, flag) == -1) {
fprintf(stderr, "fcntl: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
return 0;
}
/* 文件空洞 */
/* open create */
#include <sys/stat.h>
#include <fcntl.h>
/* read write close lseek*/
#include <unistd.h>
/* ioctl */
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main() {
ssize_t file_end, file_cur;
int fd = open("./test.txt", O_RDWR);
if(fd == -1) {
fprintf(stderr, "open: %s", strerror(errno));
return -1;
}
file_end = lseek(fd, 0, SEEK_END);
file_cur = lseek(fd, 10, SEEK_END);
write(fd, "hello\n", 6);
close(fd);
return 0;
}
/* 在文件特定偏移量处的 I/O:`pread()` 和 `pwrite()` */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd;
pread(fd)
return 0;
}
/* 分散输入和集中输出 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[]) {
int fd;
struct iovec iov[3];
struct stat my_struct;
int x;
#define STR_SIZE 100
char str[STR_SIZE];
ssize_t num_read, tot_required;
if(argc != 2 || strcmp(argv[1], "--help") == 0) {
fprintf(stderr, "Usage: %s file", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY);
if(fd == -1) {
fprintf(stderr, "open: %s", strerror(errno));
exit(EXIT_FAILURE);
}
tot_required = 0;
iov[0].iov_base = &my_struct;
iov[0].iov_len = sizeof(struct stat);
tot_required += iov[0].iov_len;
iov[1].iov_base = &x;
iov[1].iov_len = sizeof(x);
tot_required += iov[1].iov_len;
iov[2].iov_base = str;
iov[2].iov_len = STR_SIZE;
tot_required += iov[2].iov_len;
num_read = readv(fd, iov, 3);
if(num_read == -1) {
fprintf(stderr, "readv: %s", strerror(errno));
exit(EXIT_FAILURE);
}
if(num_read < tot_required) {
printf("Read fewer bytes than requested\n");
}
printf("total bytes requested: %ld; bytes read %ld\n", (long) tot_required, (long ) num_read);
return 0;
}
/* 截断文件:truncate()和 ftruncate()系统调用 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int main() {
truncate();
ftruncate();
return 0;
}
/* 使用 I/O 系统调用编写 copy 例程 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
int in_fd, out_fd;
ssize_t read_bytes;
char buf[BUFFER_SIZE];
if(argc != 3 || strcmp(argv[1], "--help") == 0) {
fprintf(stderr, "%s oldfile newfile", argv[0]);
exit(EXIT_FAILURE);
}
in_fd = open(argv[1], O_RDONLY);
if (in_fd == -1) {
fprintf(stderr, "open:%s", strerror(errno));
}
out_fd = open(argv[2], O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (out_fd == -1) {
fprintf(stderr, "open:%s", strerror(errno));
}
errno = 0;
while ((read_bytes = read(in_fd, buf, BUFFER_SIZE)) > 0) {
if(write(out_fd, buf, read_bytes) != read_bytes) {
fprintf(stderr, "write: %s", strerror(errno));
}
}
errno = 0;
if(read_bytes == -1) {
fprintf(stderr, "read: %s", strerror(errno));
exit(EXIT_FAILURE);
}
errno = 0;
if(close(in_fd) == -1) {
fprintf(stderr, "close: %s", strerror(errno));
exit(EXIT_FAILURE);
}
errno = 0;
if(close(out_fd) == -1) {
fprintf(stderr, "close: %s", strerror(errno));
exit(EXIT_FAILURE);
}
return 0;
}
/* IO 系统调用 */
/* open create */
#include <sys/stat.h>
#include <fcntl.h>
/* read write close lseek*/
#include <unistd.h>
/* ioctl */
#include <sys/ioctl.h>
int main() {
open();
creat();
read();
write();
close();
lseek()
ioctl();
return 0;
}
/* IO 系统调用 */
/* open create */
#include <sys/stat.h>
#include <fcntl.h>
/* read write close lseek*/
#include <unistd.h>
int main() {
open();
creat();
read();
write();
close();
lseek()
return 0;
}
/* tee 命令是从标准输入中读取数据,直至文件结尾,随后将数据写入标准输出和命令行参数所指定的文件 */
/* open create */
#include <sys/stat.h>
#include <fcntl.h>
/* read write close lseek*/
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define BUFF_SIZE 1024
extern int errno;
int main(int argc, const char *argv[]) {
int out_fd;
ssize_t read_bytes_num;
char buf[BUFF_SIZE];
if(argc != 2 || strcmp(argv[1], "--help") == 0) {
fprintf(stderr, "%s out-file\n", argv[0]);
return -1;
}
errno = 0;
out_fd = open(argv[1], O_WRONLY | O_CREAT, S_IWUSR);
if(out_fd == -1) {
fprintf(stderr, "open: %s\n", strerror(errno));
return -1;
}
while ((read_bytes_num = read(STDIN_FILENO, buf, BUFF_SIZE)) > 0) {
if(read_bytes_num == -1) {
fprintf(stderr, "read: %s\n", strerror(errno));
}
if(write(STDOUT_FILENO, buf, read_bytes_num) != read_bytes_num || write(out_fd, buf, read_bytes_num) != read_bytes_num) {
fprintf(stderr, "write: %s\n", strerror(errno));
}
}
errno = 0;
if(close(out_fd) == -1) {
fprintf(stderr, "close: %s\n", strerror(errno));
return -1;
}
return 0;
}
/*
动态加载库:dlopen dlsym dlerror dlclose dladdr
*/
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
void *lib_handle; /* Handle for shared library */
int ( *func_ptr)(int, int); /* Pointer to function with 2 int arguments*/
int result;
const char *err;
if(argc != 3 || strcmp(argv[1], "--help") == 0) {
fprintf(stderr, "%s lib-path func-name\n", argv[0]);
exit(EXIT_FAILURE);
}
/* load the shared library and get a handle for later use */
lib_handle = dlopen(argv[1], RTLD_LAZY);
if (!lib_handle) {
fprintf(stderr, "dlopen: %s\n", dlerror());
exit(EXIT_FAILURE);
}
/* search library for symbol named in argv[2] */
(void) dlerror(); /* clear dlerror()*/
err = dlerror();
func_ptr = dlsym(lib_handle, argv[2]);
if(err) {
fprintf(stderr, "dlsym: %s\n", err);
exit(EXIT_FAILURE);
}
/* if the address returned by dlsym() is no-NULL, try calling it as a function that takes 2 int arguments */
if ( !func_ptr) {
fprintf(stderr, "%s is NULL\n", argv[2]);
exit(EXIT_FAILURE);
}
else {
result = (*func_ptr)(1, 2);
}
printf("call %s, result is %d\n", argv[2], result);
/* dladdr() */
Dl_info info;
dladdr(func_ptr, &info);
printf("info.dli_fname = %s\n", info.dli_fname);
printf("info.dli_fbase = %p\n", info.dli_fbase);
printf("info.dli_sname = %s\n", info.dli_sname);
printf("info.dli_saddr = %p\n", info.dli_saddr);
dlclose(lib_handle);
return 0;
}
\ No newline at end of file
#include "calc.h"
extern int add(int a, int b) {
return a + b;
}
extern int sub(int a, int b) {
return a - b;
}
#ifndef _CALC_H_
#define _CALC_H_
int add(int a, int b);
int sub(int a, int b);
#endif
#include "calc.h"
#include "show.h"
int main() {
int result = add(1, 2);
show(1, '+', 2);
return 0;
}
#include <stdio.h>
#include "show.h"
#include "calc.h"
#define BUFSIZE 1024
void show(int left, char op, int right) {
char buf[BUFSIZ];
int result;
switch(op) {
case '+':
result = add(left, right);
break;
case '-':
result = sub(left, right);
break;
default:
fprintf(stderr, "Unknown operator '%c'\n", op);
return;
}
snprintf(buf, BUFSIZ, "%d %c %d = %d\n", left, op, right, result);
puts(buf);
}
#ifndef _SHOW_H_
#define _SHOW_H_
void show(int left, char op, int right);
#endif
#include "calc.h"
extern int add(int a, int b) {
return a + b;
}
extern int sub(int a, int b) {
return a - b;
}
#ifndef _CALC_H_
#define _CALC_H_
int add(int a, int b);
int sub(int a, int b);
#endif
#include "calc.h"
#include "show.h"
int main() {
int result = add(1, 2);
show(1, '+', 2);
return 0;
}
#include <stdio.h>
#include "show.h"
#include "calc.h"
#define BUFSIZE 1024
void show(int left, char op, int right) {
char buf[BUFSIZ];
int result;
switch(op) {
case '+':
result = add(left, right);
break;
case '-':
result = sub(left, right);
break;
default:
fprintf(stderr, "Unknown operator '%c'\n", op);
return;
}
snprintf(buf, BUFSIZ, "%d %c %d = %d\n", left, op, right, result);
puts(buf);
}
#ifndef _SHOW_H_
#define _SHOW_H_
void show(int left, char op, int right);
#endif
void __attribute__ ((constructor)) some_name_load(void){
/* Initialization code */
}
void __attribute__ ((deprecated)) some_name_unload(void) {
/* Finalization code */
}
\ No newline at end of file
//
// Created by dyp on 9/12/23.
//
#include <dlfcn.h>
#include <stdio.h>
int main() {
void * handle = dlopen("./libvis.so.1", RTLD_LAZY);
void (*fp)() = dlsym(handle, "vis_f1");
if(fp == NULL) {
fprintf(stderr, "dlsym:%s\n", dlerror());
return -1;
}
fp();
return 0;
}
VER_1 {
global:
vis_f1;
vis_f2;
local:
*;
};
\ No newline at end of file
#include <stdio.h>
void vis_comm() {
printf("at vis_comm.c");
}
#include <stdio.h>
void vis_comm();
void vis_f1() {
printf("at vis_f1.c call vis_comm()\n");
vis_comm();
}
#include <stdio.h>
void vis_comm();
void vis_f2() {
printf("at vis_f2.c call vis_comm()");
vis_comm();
}
#include <stdio.h>
void xyz(void) {
printf("v1 xyz\n");
}
#include <stdio.h>
__asm__(".symver xyz_old,xyz@VER_1");
__asm__(".symver xyz_new,xyz@@VER_2");
void xyz_old(void) {
printf("v1 xyz\n");
}
void xyz_new(void) {
printf("v2 xyz\n");
}
void pqr(void) {
printf("v2 pqr\n");
}
#include <stdlib.h>
int main(int argc, char *argv[]) {
void xyz(void);
xyz();
exit(EXIT_SUCCESS);
}
\ No newline at end of file
VER_1 {
global:
xyz;
local:
*;
};
\ No newline at end of file
VER_1 {
global:
xyz;
local:
*;
};
VER_2 {
global:
pqr;
} VER_1;
/* 显示进程环境变量 */
#include <stdio.h>
#include <stdlib.h>
extern char **environ; // 获取环境变量
int main(int argc, char *argv[]) {
int j;
char **ep;
// 清除环境变量
clearenv();
for(j = 1; j < argc; j++) {
// putenv 失败返回 非零0 值
if(putenv(argv[j]) != 0) {
fprintf(stderr, "putenv: fail");
exit(EXIT_FAILURE);
}
}
// setenv 失败返回 -1
if(setenv("GREET", "HELLO WORLD", 0) == -1) {
fprintf(stderr, "setenv: fail");
exit(EXIT_FAILURE);
}
unsetenv("BYE");
for(ep = environ; *ep != NULL; ep++) {
puts(*ep);
}
return 0;
}
/* 获取进程号 */
#include <unistd.h>
#include <stdio.h>
int main() {
printf("PPID: %d -> PID: %d\n", getppid(), getpid());
return 0;
}
/* 变量在进程内存各段中的位置 */
#include <stdio.h>
#include <stdlib.h>
/* 未初始化段 */
char globBuf[65536];
/* 初始化段 */
int primes[] = {2, 3, 5, 7};
/* square 在文本段 */
static int square(int x) {
/* x 和 result 在 square 的栈帧中*/
int result;
result = x * x;
return result; /* 返回值通过 rax 寄存器 */
}
static void doCalc(int val) {
printf("The square of %d is %d\n", val, square(val));
if(val < 1000) {
int t;
t = val * val * val;
printf("The cube of %d is %d\n", val, t);
}
}
int main(int argc, char *argv[]) {
/* 初始化段 */
static int key = 9973;
/* 未初始化段 */
static char mbuf[10240000];
char *p;
/* 执行 堆 内存空间 */
p = malloc(1024);
doCalc(key);
exit(EXIT_SUCCESS);
}
/* 在栈上分配空间:alloca */
#include <alloca.h>
int main() {
alloca()
return 0;
}
\ No newline at end of file
/* 堆上的内存分配:brk 和 sbrk
* 释放内存时 program break(&end) 的行为
* */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#define MAX_ALLOCS 1000000
int main(int argc, char *argv[]) {
char *ptr[MAX_ALLOCS];
int freeStep, freeMin, freeMax, blockSize, numALLOCS, j;
printf("\n");
if(argc < 3 || strcmp(argv[1], "--help") == 0) {
fprintf(stderr, "Usage: %s source dest\n", argv[0]);
exit(EXIT_FAILURE);
}
return 0;
}
/* 密码加密与用户认证:crypt 和 getpass */
#define _XOPEN_SOURCE /* crypt() */
#define _DEFAULT_SOURCE /* getpass() */
#include <unistd.h>
#include <limits.h>
#include <pwd.h>
#include <shadow.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
int main(int argc, char *argv[]) {
char *username, *password, *encrypted, *p;
struct passwd *pwd;
struct spwd *spwd;
bool authOk;
size_t len;
long lnmax;
lnmax = sysconf(_SC_LOGIN_NAME_MAX);
if(lnmax ==- 1) {
lnmax = 256;
}
/* 为用户名分配空间 */
username = malloc(sizeof(char) * lnmax);
if(username == NULL) {
fprintf(stderr, "malloc: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
printf("Usename: ");
fflush(stdout);
/* 读入用户名 */
if(fgets(username, lnmax, stdin) == NULL) {
fprintf(stdout, "fget: appear error or eof\n");
exit(EXIT_FAILURE);
}
len = strlen(username);
if(username[len - 1] == '\n') {
username[len - 1] = '\0';
}
/* 获取/etc/passwd 中获取用户名记录 */
pwd = getpwnam(username);
if(pwd == NULL) {
fprintf(stdout, "getpwnam: get passwd record fail\n");
exit(EXIT_FAILURE);
}
/*获取/etc/shadow 中获取用户名记录*/
spwd = getspnam(username);
if(spwd == NULL && errno == EACCES) {
fprintf(stdout, "getspnam: no permission to read shadow password file\n");
}
if(spwd != NULL) {
pwd->pw_passwd = spwd->sp_pwdp;
}
/* 读入一行 */
password = getpass("Password: ");
/* 对读入的密码继续加密,salt参数原加密密码的前两位 */
encrypted = crypt(password, pwd->pw_passwd);
for(p = password; *p != '\0'; ) {
*p++ = '\0';
}
if(encrypted == NULL) {
fprintf(stdout, "crypt: crypt fail\n");
exit(EXIT_FAILURE);
}
printf("pw_passwd: %s\n", pwd->pw_passwd);
printf("encrypted: %s\n", encrypted);
/* 判断是否一致 */
authOk = strcmp(encrypted, pwd->pw_passwd) == 0;
if(!authOk) {
printf("Incorrect password\n");
exit(EXIT_FAILURE);
}
printf("Successfully authenticated: UID=%d\n", pwd->pw_uid);
return 0;
}
/* 从组文件获取记录:`getgrnam()` 和 `getgrgid()` */
#include <stdio.h>
#include <grp.h>
int main() {
getgrnam();
getgrgid();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
int main() {
struct passwd *pwd;
while ((pwd = getpwent()) != NULL) {
printf("-%8s %5ld\n", pwd->pw_name, (long) pwd->pw_uid);
}
endpwent();
}
\ No newline at end of file
/* 从密码文件获取用户和组的信息: `getpwnam()` 和 `getpwuid()` */
#include <stdio.h>
#include <pwd.h>
#include <errno.h>
int main() {
// errno = 0;
// struct passwd *pd = getpwnam("dyp");
// if(pd == NULL) {
// if(errno == 0) {
// /* 未发现匹配记录 */
// } else {
// /* 出错 */
// }
// }
//
// printf("pw_name:%s\n", pd->pw_name);
// printf("pw_passwd:%s\n", pd->pw_passwd);
// printf("pw_uid:%d\n", pd->pw_uid);
printf("%d %d\n", getpwnam("dyp")->pw_uid, getpwnam("git")->pw_uid);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <shadow.h>
int main() {
struct spwd * sp;
sp = getspnam("dyp");
printf("sp_name:%s\n", sp->sp_namp);
while((sp = getspent()) != NULL) {
printf("-%8s %s\n", sp->sp_namp, sp->sp_pwdp);
}
endspent();
return 0;
}
/* 使用 `setpwent()`、`getpwent()`和 `endpwent()`来实现 `getpwnam()` */
#include <pwd.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
struct passwd * my_getpwnam(const char *name) {
struct passwd *pwd;
while ((pwd = getpwent()) != NULL) {
if(strcmp(name, pwd->pw_name) == 0) {
endpwent();
return pwd;
}
}
endpwent();
return NULL;
}
int main() {
struct passwd *pd = my_getpwnam("dyp");
if(pd == NULL) {
fprintf(stderr, "my_getpwnam: get passwd by name fail\n");
return -1;
}
printf("user:%s -> UID:%d\n", pd->pw_name, pd->pw_uid);
return 0;
}
/*
* 在用户名/组名和用户 ID/组 ID 之间互相转换的函数
* */
#include <pwd.h>
#include <grp.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
/* return pointer to username by uid, or NULL on error*/
char *userNameFromId(uid_t uid) {
struct passwd *pwd;
pwd = getpwuid(uid);
return (pwd == NULL) ? NULL : pwd->pw_name;
}
/* return uid by username, or -1 on error*/
uid_t userIdFromName(const char *username) {
struct passwd *pwd;
uid_t u;
char *endptr;
if(username == NULL || *username == '\0') {
return -1;
}
u = strtol(username, &endptr, 10);
if(*endptr == '\0') {
return u;
}
pwd = getpwnam(username);
return pwd == NULL ? -1 : pwd->pw_uid;
}
/* return pointer to groupname by uid, or NULL on error*/
char *groupNameFromId(gid_t gid) {
struct group *grp;
grp = getgrgid(gid);
return (grp == NULL) ? NULL : grp->gr_name;
}
/* return gid by gropname, or -1 on error*/
gid_t groupIdFromName(const char *gname) {
struct group *grp;
gid_t g;
char *endptr;
if(gname == NULL || *gname == '\0') {
return -1;
}
g = strtol(gname, &endptr, 10);
if(*endptr == '\0') {
return g;
}
grp = getgrnam(gname);
return grp == NULL ? -1 : grp->gr_gid;
}
int main() {
printf("uid:1000 -> name: %s\n", userNameFromId(1000));
printf("name:dyp -> uid:: %d\n", userIdFromName("dyp"));
printf("gid:1000 -> gname:%s\n", groupNameFromId(973));
printf("gname:git -> gname:%d\n", groupIdFromName("git"));
return 0;
}
\ No newline at end of file
#include "ArrayList.h"
struct seq_list {
elem_t *data;
int size;
int length;
};
\ No newline at end of file
/*
线性表的顺序存储结构
*/
typedef int elem_t;
typedef struct seq_list List;
typedef List *list_t;
main: queue.o main.o
gcc -o main queue.o main.o
queue.o: queue.c queue.h
gcc -c queue.c
main.o: main.c queue.h
gcc -c main.c
.PHONY:clean
clean:
rm *.o
rm *.exe
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册