密码学C/C++语言实现学习笔记——基本运算函数
基础数据结构:
typedef unsigned short clint;
typedef unsigned long clintd;
书中所使用环境unsigned short是16位(2个字节)的,unsigned long是32位(4个字节)的。满足非形式化公式表示的大小关系USHORTXUSHORT<=ULONG
#define CLINTMAXDIGIT 256U CLINTMAXDIGIT指定程序能处理的最大位数(0x10000进制的)。
#define CLINTMAXSHORT (CLINTMAXDIGIT + 1)
CLINTMAXSHORT指定数值存储器的大小
typedef clint CLINT[CLINTMAXSHORT]; CLINTMAXSHORT = CLINTMAXDIGIT + 1
typedef clint CLINTD[1 + (CLINTMAXDIGIT << 1)]; 1 + (CLINTMAXDIGIT << 1) = CLINTMAXDIGIT * 2 + 1
typedef clint CLINTQ[1 + (CLINTMAXDIGIT << 2)]; 1 + (CLINTMAXDIGIT << 2) = CLINTMAXDIGIT
typedef clint *CLINTPTR;
CLINT、CLINTD、CLINTQ是定义无符号短整型数组的数据类型,区别是所定义的数组大小不同。CLINTPTR是定义指向无符号短整型变量的指针类型。
声明大数的方式:
CLINT n_l;
作为表示长度的附加元素被存储在数组的第一个元素中,数值表示的数字随着存储器地址或数组索引的增加而增加。由于unsigned short是32位的,将32位存储单元存储为大数的一位,即为0x10000进制。
访问大数的位数: *n_l 即是取数组的第一个元素,存放的是大数的位数
/* CLINT-Constant Values */ CLINT类型常数值
clint nul_l[] = { 0, 0, 0, 0, 0 };
clint one_l[] = { 1, 1, 0, 0, 0 };
clint two_l[] = { 1, 2, 0, 0, 0 };
基本运算:
没有溢出检测功能和前导零检测功能的函数
void add (CLINT a_l, CLINT b_l, CLINT s_l)
void sub (CLINT a_l, CLINT b_l, CLINT d_l )
void mult (CLINT, CLINT, CLINT)
void sqr (CLINT, CLINT, CLINT)
void umul (CLINT, CLINT, CLINT)
#pragma warning(disable:4996)
参数中有USHORT类型的数据的函数
int uadd_l(CLINT a_l, USHORT b, CLINT s_l)
int usub_l(CLINT a_l, USHORT b, CLINT d_l)
int umul_l(CLINT aa_l, USHORT b, CLINT pp_l)int udiv_l(CLINT dv_l, USHORT uds, CLINT q_l, CLINT r_l)
模运算
int umadd_l(CLINT a_l, USHORT b, CLINT s_l, CLINT m_l)
int umsub_l(CLINT a_l, USHORT b, CLINT d_l, CLINT m_l)
int ummul_l(CLINT a_l, USHORT b, CLINT c_l, CLINT m_l)
USHORT umod_l(CLINT dv_l, USHORT uds)
模幂运算
int umexp_l(CLINT bas_l, USHORT e, CLINT rem_l, CLINT m_l)
运算
int inc_l(CLINT a_l)
int dec_l(CLINT a_l)
int add_l(CLINT a_l, CLINT b_l, CLINT s_l)
int sub_l(CLINT aa_l, CLINT bb_l, CLINT d_l)
int mul_l(CLINT f1_l, CLINT f2_l, CLINT pp_l)
int sqr_l(CLINT f_l, CLINT pp_l)
int div_l(CLINT, CLINT, CLINT, CLINT)
模运算
int mod_l(CLINT dv_l, CLINT ds_l, CLINT r_l)
int mod2_l(CLINT d_l, ULONG k, CLINT r_l)
int mequ_l(CLINT a_l, CLINT b_l, CLINT m_l)
int madd_l(CLINT aa_l, CLINT bb_l, CLINT c_l, CLINT m_l)
int msub_l(CLINT aa_l, CLINT bb_l, CLINT c_l, CLINT m_l)
int mmul_l(CLINT aa_l, CLINT bb_l, CLINT c_l, CLINT m_l)
int msqr_l(CLINT aa_l, CLINT c_l, CLINT m_l)
位运算与逻辑函数
int cmp_l(CLINT a_l, CLINT b_l)
int equ_l(CLINT a_l, CLINT b_l)
int shl_l(CLINT a_l)
int shr_l(CLINT a_l)
int shift_l(CLINT n_l, long int noofbits)
void xor_l(CLINT a_l, CLINT b_l, CLINT c_l)
void or_l(CLINT a_l, CLINT b_l, CLINT c_l)
void and_l(CLINT a_l, CLINT b_l, CLINT c_l)int setbit_l(CLINT a_l, unsigned int pos)
int testbit_l(CLINT a_l, unsigned int pos)
int clearbit_l(CLINT a_l, unsigned int pos)
工具类函数
unsigned int ld_l(CLINT n_l)
int vcheck_l(CLINT n_l)
void u2clint_l(CLINT num_l, USHORT u)
void ul2clint_l(CLINT num_l, ULONG ul)
char * xclint2str_l(CLINT n_l, USHORT base, int showbase)
int str2clint_l(CLINT n_l, char *str, USHORT base)
UCHAR *clint2byte_l(CLINT n_l, int *len)
int byte2clint_l(CLINT n_l, UCHAR *bytestr, int len)
char *fhexstr_l(CLINT n_l)
char *fdecstr_l(CLINT n_l)
char *foctstr_l(CLINT n_l)
char *fbinstr_l(CLINT n_l)
clint * setmax_l(CLINT a_l)
void cpy_l(CLINT dest_l, CLINT src_l)
void fswap_l(CLINT a_l, CLINT b_l)
#ifdef LINT_ASM
#ifndef FLINT_ASM
#define FLINT_ASM
#endif
#endif
如果定义了LINT_ASM,就必须定义FLINT_ASM
#ifdef LINT_ANSI
#ifndef FLINT_ANSI
#define FLINT_ANSI #endif
#endif
如果定义LINT_ANSI,就必须定义FLINT_ANSI
#ifndef __FLINT_API
#ifdef FLINT_USEDLL
#define __FLINT_API __cdecl
#else
#define __FLINT_API /**/
#endif /* FLINT_USEDLL */
#endif /* !defined __FLINT_API */如果没有定义__FLINT_API,但定义可FLINT_USEDLL,就定义__FLINT_API为__cdecl,否则定义为/**/。
#if !defined __FLINT_API_A 没有定义__FLINT_API_A
#if defined __GNUC__ && !defined __cdecl 若定义了__GNUC__ 且没有定义__cdecl
#define __FLINT_API_A /**/ 则定义__FLINT_API_A为/**/
#else
#define __FLINT_API_A __cdecl 否则定义__FLINT_API_A为__cdecl
#endif /* !defined __GNUC__ */
#endif /* !defined __FLINT_API_A */
__cdecl 是C Declaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。
VS 2017添加asm文件到工程中
/* If the FLINT/C-Package is used under MS Visual C/C++ as DLL, */
/* all modules accessing data nul_l, one_l, two_l or smallprimes from outside */
/* the DLL must be compiled with -D__FLINT_API_DATA=__declspec(dllimport) */
#ifndef __FLINT_API_DATA
#if (defined _MSC_VER && _MSC_VER >= 11) && defined FLINT_USEDLL
#define __FLINT_API_DATA __declspec(dllimport)
#else
#define __FLINT_API_DATA /**/
#endif /* MSC_VER && FLINT_USEDLL */
#endif /* !defined __FLINT_API_DATA */
#define CLINTMAXLONG ((CLINTMAXDIGIT >> 1) + 1)
#define CLINTMAXBYTE (CLINTMAXSHORT << 1)
#define CLINTMAXBIT (CLINTMAXDIGIT << 4)
(以上代码位于flint.h文件中。)
动态寄存器
通过如上图所示的数据结构,通过寄存器管理函数来对CLINT变量进行管理
对变量值进行清零
/******************************************************************************/
/* */
/* Function: Purging of variables */
/* This function can be called for purging variables by */
/* overwriting with 0. This works even in cases where compiler */
/* optimization is used, which typically causes assignments to */
/* variables or calls to memset() for automatic CLINT variables */
/* at the end of of a function to be ignored. */
/* Syntax: static void purgevars_l (int noofvars, ...); */
/* Input: noofvars (Number of following pairs of arguments) */
/* ... (noofvars pairs of (sizeof (var), (type *)var)) */
/* Output: purged variable *var */
/* Returns: - */
/* */
/******************************************************************************/
static void purgevars_l(int noofvars, ...)
{
va_list ap;
size_t size;
va_start(ap, noofvars);
for (; noofvars > 0; --noofvars)
{
switch (size = va_arg(ap, size_t))
{
case 1: *va_arg(ap, char *) = 0;
break;
case 2: *va_arg(ap, short *) = 0;
break;
case 4: *va_arg(ap, long *) = 0;
break;
default: Assert(size >= CLINTMAXBYTE);
memset(va_arg(ap, char *), 0, size);
}
}
va_end(ap);
}
/******************************************************************************/
/* */
/* Function: Check whether variables are purged with 0 */
/* Syntax: static int ispurged_l (int noofvars, ...); */
/* Input: noofvars (Number of followign pairs of arguments) */
/* ... (noofvars pairs of (sizeof (var), (typ *)var)) */
/* Output: - */
/* Returns: 1 if the arguments are purged with 0 */
/* 0 else */
/* */
/******************************************************************************/
static int ispurged_l(int noofvars, ...)
{
va_list ap;
size_t size;
char *cptr;
va_start(ap, noofvars);
for (; noofvars > 0; --noofvars)
{
size = va_arg(ap, size_t);
cptr = va_arg(ap, char *);
for (; size > 0; size--)
{
if (0 != *cptr++) return 0;
}
}
va_end(ap);
return 1;
}
VS2017中stdarg.h中的定义
#define va_start __crt_va_start
#define va_arg __crt_va_arg
#define va_end __crt_va_end
#define va_copy(destination, source) ((destination) = (source))
#define PURGEVARS_L(X) purgevars_l X
#define ISPURGED_L(X) ispurged_l X
/* Purging of variables */
PURGEVARS_L((2, sizeof(q_l), q_l,sizeof(r_l), r_l));
第一个参数指明后续的参数对的数量,参数对为类型大小+变量
ISPURGED_L((2, sizeof(q_l), q_l,sizeof(r_l), r_l));
参见征服C指针 可变长参数部分
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
void tiny_printf(char *format, ...)
{
int i;
va_list ap;
va_start(ap, format);
for (i = 0; format[i] != '\0'; i++) {
switch (format[i]) {
case 's':
printf("%s ", va_arg(ap, char*));
break;
case 'd':
printf("%d ", va_arg(ap, int));
break;
default:
assert(0);
}
}
va_end(ap);
putchar('\n');
}
int main(void)
{
tiny_printf("sdd", "result..", 3, 5);
return 0;
}
声明va_list类型的变量ap。stdarg.h文件中定义了va_list类型,在作者环境中是这样定义的:
typedef char *va_list; 也就是说va_list被定义成指向char的指针
va_start(ap, format) 意味着使指针ap指向参数format的下一个位置,因此我们得到了可变长部分的第一个参数。
给宏va_arg()指定ap和参数类型,就可以顺序地取出可变长部分的参数
va_end()是个摆设,只不过因为在标准中指出对于具有va_start()的函数需要写va_end()
在作者环境中,宏va_end()定义为: #define va_end(ap) 是个空定义。
源码网址:https://github.com/Apress/cryptography-in-c-cpp
标签:__,va,CLINT,int,笔记,ap,FLINT,C++,密码学 From: https://blog.51cto.com/feishujun/5849420