Nasm,C ++,传递类对象

时间:2016-05-08 11:03:31

标签: c++ assembly x86 nasm x86-64

我的cpp文件中有一些类。

class F{
private:
  int id;
  float o;
  float p;
  float s; 
  static int next; 
public:
  F(double o,  double s = 0.23, double p = 0.0):
  id(next++), o(o), 
  p(p), s(s){}
};

int F::next = 0;

extern "C" float pod(F f); 

int main(){
  F bur(1000,  0.23, 100);
  pod(bur);
  return 0;
}

我试图将类对象bur传递给我的asm文件中定义的函数pod。但是我从这个类对象获取值时遇到了很大的问题。

在asm计划中,0.23 XMM1100 XMM2 1000但我无法找到存储$this->set('answer',$query[0]['answers'][0]['id']); 的位置。

2 个答案:

答案 0 :(得分:1)

我不知道你为什么在xmm2中看到100,我怀疑这完全是巧合。查看结构传递方式的最简单方法是编译C ++代码。

删除了cruft后,我的编译器会这样做:

main:
.LFB3:
        .cfi_startproc
        subq    $8, %rsp
        .cfi_def_cfa_offset 16
        movl    _ZN1F4nextE(%rip), %edi    # load F::next into edi/rdi
        movq    .LC3(%rip), %xmm0          # load { 0.23, 100 } into xmm0
        leal    1(%rdi), %eax              # store rdi + 1 into eax
        movl    %eax, _ZN1F4nextE(%rip)    # store eax back into F::next
        movabsq $4934256341737799680, %rax # load { 1000.0, 0 } into rax
        orq     %rax, %rdi                 # or rax into pre-increment F::next in rdi
        call    pod
        xorl    %eax, %eax
        addq    $8, %rsp
        .cfi_def_cfa_offset 8
        ret
.LC3:
        .quad   4497835022170456064

常量4497835022170456064以十六进制为3E6B851F42C80000,如果查看最重要的四个字节(3E6B851F),则在解释为单精度时为0.23 float,最不重要的四个字节(42C80000)为100.0

同样,常量4934256341737799680(十六进制447A000000000000)的最重要的四个字节是1000.0

因此,bur.id传递了bur.ordibur.p传递了bur.sxmm0传递了rdi

x86-64 abi reference中记录了这一原因。在极端总结中,因为第一个fwo字段足够小,混合类型和其中一个是整数,它们被传递到通用寄存器(float是第一个通用参数寄存器),因为接下来的两个字段都是public class MainActivity extends AppCompatActivity { private ListView lvPhone; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lvPhone = (ListView)findViewById(R.id.listPhone); final List<PhoneBook> listPhoneBook = new ArrayList<PhoneBook>(); listPhoneBook.add(new PhoneBook(BitmapFactory.decodeResource(getResources(),R.drawable.image),"Contact_1","123456789","av1@gmail.com","1")); listPhoneBook.add(new PhoneBook(BitmapFactory.decodeResource(getResources(),R.drawable.image),"Contact_2","123456789","av2@gmail.com","2")); listPhoneBook.add(new PhoneBook(BitmapFactory.decodeResource(getResources(),R.drawable.image),"Contact_3","123456789","av3@gmail.com","3")); final PhoneBookAdapter adapter = new PhoneBookAdapter(this, listPhoneBook); lvPhone.setAdapter(adapter); lvPhone.setItemsCanFocus(false); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { final Dialog d = new Dialog(MainActivity.this); d.setTitle("Login"); d.setCancelable(true); d.setContentView(R.layout.account); d.show(); Button button_close = (Button) d.findViewById(R.id.DCancel); button_close.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { d.dismiss(); } }); Button button_login = (Button) d.findViewById(R.id.DLogin); button_login.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { String mName = new String("Ciao"); String mPhone; String mEmail; String mID; TextView TextName = (TextView) d.findViewById(R.id.DName); TextView TextPhone = (TextView)d.findViewById(R.id.DPhone); TextView TextEmail = (TextView)d.findViewById(R.id.DEmail); TextView TextID = (TextView)d.findViewById(R.id.DID); mName=TextName.getText().toString(); mPhone=TextPhone.getText().toString(); mEmail=TextEmail.getText().toString(); mID=TextID.getText().toString(); listPhoneBook.add(new PhoneBook(BitmapFactory.decodeResource(getResources(),R.drawable.image),mName,mPhone,mEmail,mID)); lvPhone.setAdapter(adapter); d.dismiss(); } }); } }); lvPhone.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { TextView TextName = (TextView) view.findViewById(R.id.tvName); TextView TextPhone = (TextView)view.findViewById(R.id.tvPhone); TextView TextEmail = (TextView)view.findViewById(R.id.tvEmail); TextView TextID = (TextView)view.findViewById(R.id.tvID); String tvName = new String(TextName.getText().toString()); String tvPhone = new String(TextPhone.getText().toString()); String tvEmail = new String(TextEmail.getText().toString()); String tvID = new String(TextID.getText().toString()); Toast.makeText(MainActivity.this, tvName, Toast.LENGTH_SHORT).show(); } }); lvPhone.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { } @Override public void onNothingSelected(AdapterView<?> arg0) { } }); } } ,它们在SSE寄存器中传递。

答案 1 :(得分:1)

您想要了解来自Agner here的调用约定编译。根据编译器,操作系统以及您是否使用32位64位,可能会发生不同的事情。 (见表5第7章)。

对于64位linux,例如,由于您的对象包含不同的值(参见表6),R案例似乎适用:

  

如果大小不大于128位,则整个对象在整数寄存器和/或XMM寄存器中传输,否则在堆栈上传输。如果对象的每个64位部分仅包含float或double,则在XMM寄存器中传输;如果它包含整数类型或混合整数和float,则在整数寄存器中传输。可以将两个连续的浮点数打包到一个XMM寄存器的下半部分。

在您的情况下,该类适合128位。来自@CharlesBailey的实验说明了这种行为。根据惯例

  

...或在整数寄存器中,如果它包含整数类型或混合整数和浮点数。两个连续的浮点数可以打包到一个XMM寄存器的下半部分。示例:int和float:RDI。

第一个int注册rdi应该ido xmm0应该包含ps

在xmm2中看到100可能是初始化的副作用,因为它作为double传递给结构构造函数。