当前位置: 首页 > 知识库问答 >
问题:

cmp之后的程序集x86调用

魏刚豪
2023-03-14

我有以下代码来比较数字并增加一个变量,如果真或假

failcheck1:
            mov eax, val1
            add ebx, 4
            cmp eax, 40
            jl failinc1

            mov eax, passes
            inc eax
            mov passes, eax
            jmp failcheck2

failinc1:
            mov eax, fails
            inc eax
            mov fails, eax


failcheck2 :
            mov eax, val2
            add ebx, 4
            cmp eax, 40
            jl failinc2

            mov eax, passes
            inc eax
            mov passes, eax
            jmp failcheck3

failinc2:
            mov eax, fails
            inc eax
            mov fails, eax

我有8个这样的检查。我想知道,如果我创建了一个包含ret的单Failinc和passinc子程序,我如何在cmp之后调用它?

共有2个答案

宋烨烁
2023-03-14
failcheck:
    mov eax, [eax]
    add ebx, 4
    cmp eax, ecx
    jl .L1
    incl passes
    ret
.L1:
    incl fails
    ret

failcheck1:
    lea eax, val1
    mov ecx, 40
    call failcheck

    lea eax, val2
    mov ecx, 40
    call failcheck
仲法
2023-03-14

由于 EBX 是独立递增的,因此您可以将 8 加 ebx、4 替换为单个加法 ebx、4*8

通过使用条件集指令setl(set On Less),可以避免所有这些难看且耗时的条件跳转。

因为失败和传递是互斥的,所以可以将计算传递推迟到最后。e、 g.如果处理给定的8个值3失败,则不可避免地必须通过5次(8减3)。

 xor  ecx, ecx    ;Clear because SETL only operates on a byte
 xor  edx, edx    ;Clear temporary counter of fails

 cmp  val1, 40
 setl cl
 add  edx, ecx    ;Conditionally increment temporary counter
 cmp  val2, 40
 setl cl
 add  edx, ecx    ;Conditionally increment temporary counter
 cmp  val3, 40
 setl cl
 add  edx, ecx    ;Conditionally increment temporary counter
 cmp  val4, 40
 setl cl
 add  edx, ecx    ;Conditionally increment temporary counter
 cmp  val5, 40
 setl cl
 add  edx, ecx    ;Conditionally increment temporary counter
 cmp  val6, 40
 setl cl
 add  edx, ecx    ;Conditionally increment temporary counter
 cmp  val7, 40
 setl cl
 add  edx, ecx    ;Conditionally increment temporary counter
 cmp  val8, 40
 setl cl
 add  edx, ecx    ;Conditionally increment temporary counter

 add  fails, edx  ;Add temporary counter to actual variable
 sub  edx, 8
 sub  passes, edx ;Add complementary count to other variable (*)

 add  ebx, 4*8

我想知道如果我创建了一个带有ret的失败和传递子例程,我怎么能在cmp之后调用它?

现在子程序

AddTempCount:     ;On input EFLAGS is set from CMP instruction
 setl cl
 add  edx, ecx    ;Conditionally increment temporary counter
 ret

可以提高一点可读性。

 xor  ecx, ecx    ;Clear because SETL only operates on a byte
 xor  edx, edx    ;Clear temporary counter of fails

 cmp  val1, 40
 call AddTempCount
 cmp  val2, 40
 call AddTempCount
 cmp  val3, 40
 call AddTempCount
 cmp  val4, 40
 call AddTempCount
 cmp  val5, 40
 call AddTempCount
 cmp  val6, 40
 call AddTempCount
 cmp  val7, 40
 call AddTempCount
 cmp  val8, 40
 call AddTempCount

 add  fails, edx  ;Add temporary counter to actual variable
 sub  edx, 8
 sub  passes, edx ;Add complementary count to other variable (*)

 add  ebx, 4*8

(*)减去负计数与添加正计数相同。

 类似资料:
  • 这是一个用于x86处理器的简单dos汇编程序。这是一个简单的helloworld程序。 我不明白的是图像中下面的连续内存地址。程序似乎从十六进制中的地址0100开始,即256。下一个地址是258。差异似乎是2个字节。是不是这样指令(操作码地址)是2个字节? 然后再往下-mov dx指令似乎占用3个字节(0117-011A),而mov ah指令占用2个字节。 我以为指令(操作码地址)应该在内存中占用

  • 问题内容: 在学习“汇编语言”(在Linux中,使用GNU作为汇编语言的x86体系结构)的同时,其中一件令人惊奇的事情是可以使用系统调用。这些系统调用非常方便,有时甚至需要在程序在用户空间中运行时使用。 但是,系统调用在性能方面相当昂贵,因为它们需要中断(当然还有系统调用),这意味着必须从用户空间中当前的活动程序到内核空间中运行的系统进行上下文切换。 我要说的是:我目前正在实现一个大学项目的编译器

  • 问题内容: asm_execve.s: 生成文件: 程序已执行,但未调用sys_execve: 预期输出为: 该Assembly程序应该像以下C代码一样工作: 系统调用参数有问题吗? 问题答案: 该系统调用 时 被调用,但你确实传递错误参数。 (您可以通过使用运行可执行文件来查看此内容。) 存在三个问题: 不以0结尾的字符串。(您可能会很幸运,因为在此示例中的本节中没有任何内容,但是不能保证…)添

  • 下面是我的c函数: 如果str[i]=='a',则将设置zflag,je.L5将接受分支。如果str[i]!='a',则将清除zflag。je.L5不会拿树枝。 为什么编译器在cmpb指令后生成两行额外的代码?

  • 我试图清楚地了解谁(调用者或被调用者)负责堆栈对齐。64位程序集的情况相当清楚,它是由调用者完成的。 参考System V AMD64 ABI,第3.2.2节堆栈框架: 输入参数区域的末尾应在16(32,如果__m256在堆栈上传递)字节边界上对齐。 换句话说,应该可以安全地假设,对于被调用函数的每个切入点: 保持(额外的8是因为调用隐式地将返回地址推送到堆栈上)。 它在32位世界中看起来如何(假

  • 假设我有以下 C 代码: 当< code>x == INT_MAX时,这是未定义的行为。现在假设我用内联汇编执行了加法: 问题:当< code>x == INT_MAX时,内联汇编版本是否仍然调用未定义的行为?还是未定义的行为只适用于C代码?