【问题标题】:Comparing a 32 bit file size to 16 bit user input?将 32 位文件大小与 16 位用户输入进行比较?
【发布时间】:2017-11-07 15:26:59
【问题描述】:

我正在编写一个汇编程序,它分析文件并将它们的信息(名称和大小)输出到文件中。我基本上使用 4Eh 和 4Eh 中断来搜索文件:它们都返回 DTA 对象,其中包含有关该文件的相应信息。

它返回一个 32 位文件大小,我必须将其与 16 位用户输入大小进行比较(如果文件信息大于给定的用户输入大小,我必须只输出文件信息)。

这里明显的问题是我不知道如何将 32 位数字转换为 16 位数字,否则我无法比较它们。也许有人知道如何执行这种转换或对如何实现这种比较有任何其他想法?

如果可能,也许有人可以在 TASM Intel x86 程序集中提供示例代码

【问题讨论】:

  • 显然,如果文件大小的前 16 位非零,则它比您的用户输入的数字更大。如果它们为零,那么您有两个可以比较的 16 位数字。容易。
  • 0..65535 范围内的值将适合 16 位(高 16 位将为零)。 65536+ 值将在高 16 位中有一些非零位。如果您的应用仅将 16 位值 (0..65535) 作为输入,那么您可以先通过检查高 16 位来检查长度是否 >= 65536。

标签: assembly x86 tasm


【解决方案1】:

你在往后想。

您希望将 16 位数字零扩展为 32,并进行 32 位比较。 (在 C 中,对不同类型的操作会提升为足够宽以容纳它们的类型,因为这几乎总是你想要的。)

正如 Jester 所解释的,这意味着用户输入的前 16 位始终为零,因此进行扩展精度/BigInteger 比较的上半部分只是检查文件大小的上半部分是否为非零。然后,如果文件大小足够小,可能低于 16 位用户输入,则将下半部分与阈值进行比较。


您还可以通过执行扩展精度减法,仅使用一条分支指令检查小于:

file_loop:               ; do {
    load a new file size

    ;; file size in dx:ax,  threshold in cx
    cmp    ax, cx        ; low half (non-destructive: cmp = sub but without writing ax)
    sbb    dx, 0         ; high half. (destructive)
    ; ZF reflects only the high-half compare result
    ; CF is useful (and so are SF/OF for signed compare).
    ; Avoid JCC conditions that depend on ZF, like JA.
    jnb   file_loop    ; } while(CF==0);   (JNB = JNC)

;;; dx:ax < 0:cx unsigned was true.
;;; So we know the original DX was 0 (and is now 0xFFFF)
;;; AX = the file size (which we didn't destroy), and we know it fits in 16 bits.

    do something with this file
    jmp  file_loop

这很好而且很紧凑,但可能并不比cmp/jzcmp/jb 特别好,尤其是当32 位数字在内存中时。 (您不想将sbb 与内存目标一起使用;这样效率较低。)


转换 32->16 很简单:只需通过忽略高 16 位来截断。但你似乎已经意识到,这不会如你所愿。

要回答您的旧标题:要将 dx:ax 中的 32 位整数转换为 cx 中的 16 位整数,请使用以下指令:mov cx, ax

【讨论】:

  • 这是否意味着,以同样的方式,我可以比较 8 位和 32 位数字?我的意思是,如果我将 32 位数字分成 4 个 8 位数字(两个高位,两个低位),因此我可以假设任何高位或最左边的低位中是否有任何非零数字,那么数字更高比任何 8 位数字。否则,我可以将 32 位数字的最右下部分与 8 位数字进行比较。
  • @JonasPetraška:是的,但请注意,您仍然可以一步检查 32 位数字的高 16,因为 8086 是 16 位架构。您也可以movzx (386) 或xor ax,ax / mov al, single_byte 将您的 8 位数字零扩展为 16,然后您可以对 32 位数字的低半部分进行 16 位比较。
  • @PeterCorder:非常感谢!
  • @JonasPetraška 还请记住(在检查内存中的单独字节时)x86 是小端,因此 DTA 中的文件大小很可能在 LE 中也是如此,即大小 66051 在内存中存储为 4 个字节03 02 01 00,所以最低 8 位在偏移 +0,最高 8 位在 +3 地址。 ...即从内存中检查上 16b 是否为零:xor ax,axcmp [dta_fsize+2],axjnz size_above_65535mov ax,[dta_fsize] ; = lower 16 bits (value 0..65535).
  • 还相关:您可以查看 C 编译器输出(对于 32 位模式下的 64 位整数)以查看它使用了哪些指令。 godbolt.org/z/crPYb3Kf8。对于== 等其他比较,只需更改 C 源代码即可。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-01
  • 1970-01-01
  • 2015-04-27
  • 2019-05-17
  • 1970-01-01
  • 1970-01-01
  • 2021-07-11
相关资源
最近更新 更多