我刚开始学习WinAPI。 在MSDN中,为WORD数据types提供了以下说明。
字
一个16位无符号整数。 范围是0到65535十进制。
这个types在WinDef.h中声明如下:
typedef unsigned short WORD;
很简单,它与我一直用来学习的其他资源相匹配,但它怎么可以明确地说,它是16位? 维基百科上的C数据types页面指定
short / short int / signed short / signed short int
短签名整数types。
能够至less包含[-32767,+32767]范围; 因此它至less有 16位的大小。
如何将C运行时库链接到“ld”?
在linux下混合编程和C语言
如何获得硬盘序列号在C或asm没有wmi
在linux系统上学习x64
所以根据C标准, short的大小short可能是32位。 但谁决定使用什么样的比特尺寸呢? 我在这里find一个实际的解释 。 具体而言,该行:
…这取决于两个处理器(更具体地说,ISA,指令集架构,例如x86和x86-64)和编译器,包括编程模型。
所以这是ISA,这是有道理的,我想。 这是我迷路的地方。 看看维基百科上的Windows页面 ,我可以在侧面看到:
平台ARM,IA-32,Itanium,x86-64,DEC Alpha,MIPS,PowerPC
我真的不知道这些是什么,但我认为这些是处理器,每个将有一个ISA。 也许Windows支持这些平台,因为所有这些平台都保证使用16位作为unsigned short ? 这听起来不太对,但我对这个东西还没有足够的了解。
回到我的问题:Windows API如何能够inputtypedef unsigned short WORD; 那么当C标准本身不能保证一个总是16位时, WORD是一个16位无符号整数?
与气体组装时推送的指令后缀无效
如何在C中find函数的返回地址?
在LLVM上的Syscall / sysenter
我怎样才能在我的64位机器上用gcc编译一个32位的.o文件?
如何访问我的英特尔芯片组的特定registry?
简而言之,一个WORD总是16位。
由于WORD总是16位,但是unsigned short不是,所以WORD并不总是unsigned short 。
对于Windows SDK支持的每个平台,Windows头文件包含#ifdef样式的宏,它们可以检测编译器及其平台,并将Windows SDK定义的类型( WORD , DWORD等)关联到相应大小的平台类型。
这就是为什么Windows SDK实际使用内部定义的类型,如WORD ,而不是使用语言类型:以便他们可以确保它们的定义总是正确的。
微软工具链附带的Windows SDK可能是懒惰的,因为微软的c ++工具链总是使用16位无符号短裤。
我不会指望随Visual Studio C ++一起提供的windows.h如果放到GCC,clang等等中,就能正常工作,因为很多细节,包括导入dll使用平台SDK分发的.iib文件的机制,都是Microsoft特定的实现。
不同的解释是:
微软说WORD是16位。 如果“某人”想要调用一个Windows API,那么它们必须传递一个16位值,API将该字段定义为WORD。 微软也可能会说,为了构建一个有效的Windows程序,使用Windows SDK中存在的Windows头文件,用户必须选择一个16位short的编译器。
c ++规范并没有说编译器必须以16位来实现short s,微软说你选择编译windows可执行文件的编译器必须这样做。
最初有一个假设,所有打算在Windows上运行的代码都要用微软自己的编译器编译 – 或者一个完全兼容的编译器。 这就是它的工作方式。 Borland C:匹配的微软C. Zortech的C:匹配的微软C. gcc:没有太多,所以你甚至没有尝试(更不用说没有运行时等)。
随着时间的推移,这个概念被编纂并扩展到了其他操作系统(或者其他操作系统首先得到它),现在它被称为ABI- 应用程序二进制接口 – 对于一个平台,假设所有该平台的编译器练习,需要)来匹配ABI。 这意味着匹配整数类型(除其他外)的大小的期望。
你没有问的一个有趣的相关问题是:为什么16位称为一个单词 ? 为什么我们的32位和64位体系结构中的32位是双字(双字),本地机器的“字”大小是32位还是64位,而不是16位? 因为:80286。
在Windows头文件中有很多基于平台的#define可以确保WORD是16位,DWORD是32等。在过去的某些情况下,我知道他们为每个平台分配一个合适的SDK。 在任何情况下,没有什么魔术,只是正确的#defines和标题的混合物。
对于BYTE=8bits , BYTE=8bits , WORD=16bits , DWORD=32bits (双字)术语来自Intel的指令助记符和文档。这只是术语,在这一点上并不意味着“机器字“在运行代码的实际机器上。
我猜:
这些C型名称最初可能是由于与C99标准化的uint8_t , uint16_t和uint32_t相同的原因而引入的。 这个想法可能允许具有不兼容的ABI(例如16位int或32位short )的C实现继续编译使用WinAPI的代码,因为ABI在struct s中使用DWORD而不是long或int ,并且函数参数/返回值。
可能随着Windows的发展,足够多的代码开始以各种方式对WORD和DWORD的精确定义,MS决定对标准化的typedef进行标准化 。 这与C99 uint16_t想法不同,在这里你不能认为它是unsigned short 。
正如@supercat指出的那样 ,这可能会影响别名规则。 例如,如果您通过DWORD*修改了unsigned long[]的数组,则可以保证它将按预期工作。 但是,如果通过DWORD*修改一个unsigned int[]数组,编译器可能会认为它不会影响寄存器中已有的数组值。 这对于printf格式的字符串也很重要。 (C99的<stdint.h>解决方案就是像PRIu32这样的预处理宏 。)
或者,也许这个想法只是使用与asm匹配的名称 ,以确保没有人对类型的宽度感到困惑。 在Windows的早期,直接用asm编写程序,而不是C,很受欢迎。 WORD / DWORD使得用户在写入文档时更清晰。
或者,也许这个想法只是为可移植代码提供一个固定宽度的类型 。 例如#ifdef SUNOS :将其定义为该平台的适当类型。 正如你注意到的,在这一点上,这一切都是好事。
Windows API如何能够输入unsigned short WORD; 那么当C标准本身不能保证一个总是16位时,WORD是一个16位无符号整数?
你是正确的,记录确切的typedef意味着在一个使用不同ABI的系统(例如一个long 64位或short 32位)的系统中正确实现WinAPI头文件是不可能的。 这是x86-64 Windows ABI long 32bit类型的原因之一。 x86-64 System V ABI(Linux,OS X等)使64位类型变long 。
但是,每个平台都需要一个标准的ABI 。 struct布局,甚至函数参数的解释,都要求所有的代码在所用类型的大小上达成一致。 来自相同C编译器的不同版本的代码可以互操作,甚至可以遵循相同ABI的其他编译器。 (但是,C ++ ABIs不够标准化,例如g++从未标准化过ABI,而新版本则会破坏ABI的兼容性。
请记住,C标准只告诉你在每个合格的C实现中你可以假定什么。 C标准还指出,有符号整数可能是符号/量级,补码或二进制补码。 不过,任何具体的平台都将使用硬件的任何表示。
平台可以自由地标准化基本C标准未定义或实现定义的任何内容。 例如,x86 C实现允许创建未对齐的指针存在,甚至取消引用它们。 这种情况在__m128i矢量类型中发生了很多。
所选择的实际名称将WinAPI与x86的传统相结合,不幸的是,任何不熟悉x86 asm或至少Windows的16位DOS遗产的人都会感到困惑。
8086指令助记符包括w对于word和d对dword通常用作idiv符号除法的设置。
cbw :将AL(字节)扩展为AX(字)
cwd :符号将AX(word)扩展为DX:AX(dword) , 即将 ax的符号位复制到dx每一位。
这些insn在32bit和64bit模式下依然存在,并且完全一样。 (386和x86-64增加了扩展版本,正如你可以在英特尔的insn set引用的提取中看到的那样)。还有lodsw , rep movsw等字符串指令。
除了这些助记符,操作数的大小需要在某些情况下明确指定,例如
mov dword ptr [mem],-1 ,其中两个操作数都不是可以指示操作数大小的寄存器。 (要看看汇编语言是什么样的,只需要反汇编一下,例如在Linux系统上, objdump -Mintel -d /bin/ls | less 。)
所以这个术语在x86 asm中已经遍地开花了,这是开发ABI时需要熟悉的东西。
更多的x86 asm背景,历史和当前的命名方案
没有低于这一点与WinAPI或原始问题有关,但我认为这很有趣。
另请参阅x86标记维基以获取有关英特尔官方PDF(以及其他许多好东西)的链接。 这个术语在英特尔和AMD的文档和指令助记符中是无处不在的,因为它在一个特定的体系结构的文档中是完全明确的,并且一致地使用它。
386扩展寄存器大小为32位,并引入了cdq指令: cdq (eax(dword) – > edx:eax(qword))。 (也引入了movsx和movzx来movzx或者零扩展,而不需要首先将数据写入eax )无论如何,四字是64位的,并且甚至在386之前的版本中用于fld qword ptr [mem] double精度内存操作数fld qword ptr [mem] / fst qword ptr [mem] 。
英特尔仍然使用这个b / w / d / q / dq惯例来进行向量指令命名 ,所以它根本不是他们试图逐步淘汰的东西。
例如pshufd insn助记符( _mm_shuffle_epi32 C内部 )被_mm_shuffle_epi32 (整数)Shuffle Dword。 psraw是psraw右移算术字。 (FP向量insns使用ps (压缩单个)或pd (压缩双向)后缀而不是p前缀。)
随着向量变得越来越宽,命名开始变得愚蠢:例如, _mm_unpacklo_epi64是 punpcklqdq指令 的固有 punpcklqdq :Packed-integer将L四元组punpcklqdq为Double-Quad。 (即将64位低半部分交织成一个128b)。 或移动Double-Quad未对齐的加载/存储的movdqu (16个字节)。 一些汇编程序使用o (八字)来声明16字节的整数常量,但英特尔助记符和文档总是使用dq 。
幸运的是,为了我们的理智,AVX 256b(32B)指令仍然使用SSE助记符,所以vmovdqu ymm0,[rsi]是一个32B的负载,但是没有quad-quad的术语。 包含操作数大小的反汇编程序即使vmovdqu ymm0,ymmword ptr [rsi]也会打印vmovdqu ymm0,ymmword ptr [rsi] 。
甚至一些AVX-512扩展名的名称都使用b / w / d / q术语。 AVX-512F(基础)不包括每个指令的所有元素大小的版本。 某些指令的8位和16位元件尺寸版本仅在支持AVX-512BW扩展的硬件上可用。 AVX-512DQ还有额外的dword和qword元素大小的指令,包括float / double和64bit整数之间的转换以及64b x 64b => 64b元素大小的乘法 。
一些新的说明在助记符中使用数字大小
AVX的vinsertf128和类似的提取一个256位矢量的高128位通道可能已经使用dq ,而是使用128 。
AVX-512引入了一些名称为vmovdqa64 (64位元素粒度的向量加载掩码)或vshuff32x4 (随机128位元素,32位元素粒度掩蔽)的insn助记符。
请注意,由于AVX-512对几乎所有指令都进行了合并屏蔽或零屏蔽,所以甚至不需要关心元素大小的指令(如pxor / _mm_xor_si128 )现在都有不同的大小: _mm512_mask_xor_epi64 ( vpxorq )位影响64位元素)或_mm512_mask_xor_epi32 ( vpxord )。 无掩码内部_mm512_xor_si512可以编译为vpxorq或vpxord ; 没关系。
大多数AVX512新指令在其助记符中仍然使用b / w / d / q,但像VPERMT2D (从两个源矢量中选择全部置换元素)一样。
目前没有支持Windows API的平台,但是没有unsigned short不是16位。
如果有人曾经制作过这样的平台,那么该平台的Windows API头文件将不包含行typedef unsigned short WORD; 。
您可以将MSDN页面视为描述x86 / x64平台上MSVC ++的典型行为。
像WORD这样的类型的传统使Windows早于由MASM定义的类型(后来名称改为ML)的时代早于MSDOS的时代。 未被Windows API采用的是MASM的签名类型,如SBYTE,SWORD,SDWORD,SQWORD。
MASM中的QWORD / SQWORD可能直到MASM / ML支持80386才被定义。
当前参考:
http://msdn.microsoft.com/en-us/library/8t163bt0.aspx
Windows添加了诸如HANDLE,WCHAR,TCHAR等类型。
对于Windows / Microsoft编译器,size_t是一个无符号整数,与poitner的大小相同,如果是32位模式则是32位,如果是64位模式则是64位。
MASM中的DB和DW数据指令可以回溯到Intel8080汇编程序的日子。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。