将浮点数从指针加载到float并推入堆栈

时间:2015-06-24 14:00:42

标签: gcc x86 nasm

这是一项家庭作业。我有一个C程序调用NASM实现的函数calc(int, float*, float*, float*, float*)。我想用从C传递的数据进行浮点除法,但首先我想检查一下是否正确访问了数据。

这是C程序的摘录:

printf("read.c: F data1[0]=%f\n", data1[0]);
printf("read.c: X data1[0]=%X\n", *(int*)(&data1[0]));
calc(nlines, data1, data2, result1, result2);

为了进行测试,我想从汇编程序代码中打印出完全相同的内容,但无论我尝试什么,它都不会给我正确的结果。确切地说,输出%X格式会得到相同的结果,但%f格式会给出一些非常大的数字。

global calc
extern printf

; -----------------------------------------------------------------------
; extern void calc(int nlines, float* data1, float* data2,
;           float* result1, float* result2)
; -----------------------------------------------------------------------
calc:
  section .data
  .strf db "calc.asm: F data1[0]=%f", 10, 0
  .strx db "calc.asm: X data1[0]=%X", 10, 0
  section .text

  enter 0, 0

  ; Move the value of float* data1 into ecx.
  mov ecx, [esp + 12]

  ; Move the contents of data1[0] into esi.
  mov esi, [ecx]

  push esi
  push .strf
  call printf
  add esp, 8

  push esi
  push .strx
  call printf
  add esp, 8

  leave
  ret

输出

read.c: F data1[0]=20.961977
read.c: X data1[0]=41A7B221
calc.asm: F data1[0]=-8796958457989122902187458235483374032941932827208012972482327255932202912296419757153331437662235555722313731094096197990916443553479942683040096290755684437514827018615169352974748429901549205109479495668937369584705401541113350145698235773041651907978442730240007381959397006695721667307435228446926569472.000000
calc.asm: X data1[0]=41A7B221

我也调查了fld,但是我无法知道如何在堆栈上推送加载的值。这没有用:

; Move float* data1 into ecx
mov ecx, [esp + 12]

; Load the floating point number into esi.
fld dword [ecx]
fst esi

如何正确做到?

我已将read.c删除此代码

#include <stdio.h>
#include <stdlib.h>
#define MAXLINES 1024
extern void calc(int, float*, float*, float*, float*);
int main(int argc, char** argv)
{
  int nlines;
  float* data1 = malloc(sizeof(float)*MAXLINES);
  float*data2, *results1, *results2;

  printf("read.c: F data1[0]=%f\n", data1[0]);
  printf("read.c: X data1[0]=%X\n", *(int*)(&data1[0]));
  calc(nlines, data1, data2, results1, results2);
  return 0;
}

这是汇编程序输出:

.file   "test.c"
    .section    .rodata
.LC0:
    .string "read.c: F data1[0]=%f\n"
.LC1:
    .string "read.c: X data1[0]=%X\n"
    .text
    .globl  main
    .type   main, @function
main:
.LFB2:
    .cfi_startproc
    pushl   %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $64, %esp
    movl    $4096, (%esp)
    call    malloc
    movl    %eax, 44(%esp)
    movl    44(%esp), %eax
    flds    (%eax)
    fstpl   4(%esp)
    movl    $.LC0, (%esp)
    call    printf
    movl    44(%esp), %eax
    movl    (%eax), %eax
    movl    %eax, 4(%esp)
    movl    $.LC1, (%esp)
    call    printf
    movl    60(%esp), %eax
    movl    %eax, 16(%esp)
    movl    56(%esp), %eax
    movl    %eax, 12(%esp)
    movl    52(%esp), %eax
    movl    %eax, 8(%esp)
    movl    44(%esp), %eax
    movl    %eax, 4(%esp)
    movl    48(%esp), %eax
    movl    %eax, (%esp)
    call    calc
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
.LFE2:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
    .section    .note.GNU-stack,"",@progbits


.LC1:
  .string "read.c: F data1[0]=%f\n"
.LC2:
  .string "read.c: X data1[0]=%X\n"
  .text
  .globl  main
  .type main, @function
main:
.LFB4:
  .cfi_startproc
  pushl %ebp
  .cfi_def_cfa_offset 8
  .cfi_offset 5, -8
  movl  %esp, %ebp
  .cfi_def_cfa_register 5
  andl  $-16, %esp
  subl  $64, %esp
  movl  44(%esp), %eax
  flds  (%eax)
  fstpl 4(%esp)
  movl  $.LC1, (%esp)
  call  printf
  movl  44(%esp), %eax
  movl  (%eax), %eax
  movl  %eax, 4(%esp)
  movl  $.LC2, (%esp)
  call  printf
  movl  60(%esp), %eax
  movl  %eax, 16(%esp)
  movl  56(%esp), %eax
  movl  %eax, 12(%esp)
  movl  52(%esp), %eax
  movl  %eax, 8(%esp)
  movl  44(%esp), %eax
  movl  %eax, 4(%esp)
  movl  48(%esp), %eax
  movl  %eax, (%esp)
  call  calc
  movl  $0, %eax
  leave
  .cfi_restore 5
  .cfi_def_cfa 4, 4
  ret
  .cfi_endproc
.LFE4:
  .size main, .-main
  .ident  "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4"
  .section  .note.GNU-stack,"",@progbits

1 个答案:

答案 0 :(得分:1)

好的,我现在有机会对此进行测试并验证我在评论中建议的内容。这是我修改后的汇编代码版本,附带一些注释来解释我添加/更改的内容:

global _calc
extern _printf

; -----------------------------------------------------------------------
; extern void calc(int nlines, float* data1, float* data2,
;           float* result1, float* result2)
; -----------------------------------------------------------------------
_calc:
  section .data
  .strf db "calc.asm: F data1[0]=%f", 10, 0
  .strx db "calc.asm: X data1[0]=%X", 10, 0
  section .text

  enter 0, 0

  ; Move the value of float* data1 into ecx.
  mov ecx, [esp + 12]

  ; Move the contents of data1[0] into esi.
  mov esi, [ecx]

  fld dword [ecx]    ; Load a single-precision float onto the FP stack.
  sub esp,8          ; Make room for a double on the stack.
  fstp qword [esp]   ; Store the top of the FP stack on the regular stack as
                     ; a double, and pop it off the FP stack.
  push .strf
  call _printf
  add esp, 12        ; 12 == sizeof(char*) + sizeof(double) 

  push esi
  push .strx
  call _printf
  add esp, 8

  leave
  ret