首页 \ 问答 \ rep_movsl的Clobber列表(Clobber list for rep_movsl)

rep_movsl的Clobber列表(Clobber list for rep_movsl)

我正在尝试内联汇编的例子: http//www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html但是有些东西令我对打扰感到困惑:

  • 关于clobber的行为
    Clobbering基本上告诉GCC不相信指定寄存器/存储器中的值。

    “好吧,当优化时,它确实有帮助,当GCC可以确切地知道你在前后的寄存器中做什么......它甚至足够聪明,知道如果你告诉它把(x + 1)放入寄存器,那么如果你不打开它,后来的C代码指的是(x + 1),并且它能够保持该寄存器空闲,它将重新使用计算。

这个段落是否意味着clobbering会禁用常见的子表达式消除?

  • 关于clobber列表的教程有些不一致:
    对于输入/输出列表中指定的寄存器,GCC不需要将它们置于clobber列表中; 但是,在关于rep_movsl(或rep_stosl)的示例中:

    asm(“cld \ n \ t”“rep \ n \ t”“stosl”:/ *没有输出寄存器* /:“c”(count),“a”(fill_value),“D” %ecx“,”%edi“);

虽然“S,D,c”在输出操作数中,但它们被列为再次被破坏。 我在C中尝试了一个简单的片段:

#include<stdio.h>
int main()
{
  int a[] = {2, 4, 6};
  int b[3];
  int n = 3;
  int v = 12;
  asm ("cld\n\t"
       "rep\n\t"
       "movsl"
       :
       : "S" (a), "D" (b), "c" (n)
       : );
//     : "%ecx", "%esi", "%edi" );
  printf("%d\n", b[1]);
}

如果我使用评论的clobber列表,GCC会抱怨:

ac:8:3:错误:在重新加载'asm'时无法在类'CREG'中找到寄存器ac:8:3:错误:'asm'操作数具有不可能的约束

如果我使用空的clobber列表,它将编译并且输出为4。


I'm trying out the examples of inline assembly in: http://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html But something is confusing me about clobbering:

  • About behavior of clobber
    Clobbering essentially tells GCC to not trust the values in the specified register/memories.

    "Well, it really helps when optimizing, when GCC can know exactly what you're doing with the registers before and after....It's even smart enough to know that if you tell it to put (x+1) in a register, then if you don't clobber it, and later C code refers to (x+1), and it was able to keep that register free, it will reuse the computation. Whew."

Does this paragraph means clobbering will disable common sub-expression elimination?

  • There's some inconsistency in the tutorial about the clobber list:
    For registers specified in input/output list, there's no need to put them in clobber list as GCC knows; However in the example about rep_movsl (or rep_stosl):

    asm ("cld\n\t" "rep\n\t" "stosl" : /* no output registers */ : "c" (count), "a" (fill_value), "D" (dest) : "%ecx", "%edi" );

although "S, D, c" are in the output operands, they are listed as clobbered again. I tried a simple snippet in C:

#include<stdio.h>
int main()
{
  int a[] = {2, 4, 6};
  int b[3];
  int n = 3;
  int v = 12;
  asm ("cld\n\t"
       "rep\n\t"
       "movsl"
       :
       : "S" (a), "D" (b), "c" (n)
       : );
//     : "%ecx", "%esi", "%edi" );
  printf("%d\n", b[1]);
}

If I use the commented clobber list, GCC will complain:

a.c:8:3: error: can't find a register in class ‘CREG’ while reloading ‘asm’ a.c:8:3: error: ‘asm’ operand has impossible constraints

If I use empty clobber list, it will compile and the output is 4.


原文:https://stackoverflow.com/questions/13258464
更新时间:2022-04-05 07:04

最满意答案

大卫布拉班特让你已经朝着正确的方向发展(如果你想与DICOM合作,你一定要阅读并珍惜dclunie的医学影像常见问题 )。 让我们看看我是否可以详细阐述它,并使其更容易实施。

我假设你有一个工具/库来从DICOM文件中提取标签(Offis'DCMTK?)。 为了举例说明,我将参考CT扫描(许多切片,即许多图像)和一个侦察图像,您要在其上显示定位线。 每个DICOM图像(包括您的CT片和您的侦察器)都包含有关它们在太空中的位置的完整信息,在这两个标签中:

Group,Elem  VR Value                           Name of the tag   
---------------------------------------------------------------------
(0020,0032) DS [-249.51172\-417.51172\-821]  # ImagePositionPatient
                X0         Y0         Z0

(0020,0037) DS [1\0\0\0\1\0]                 # ImageOrientationPatient
                A B C D E F

ImagePositionPatient以(x,y,z)表示的传输的第一个像素(左上角像素,清晰)的全局坐标为mm。 我将它们标记为X0,Y0,Z0。 ImageOrientationPatient包含两个矢量,它们都是三个分量,用于指定第一行像素的方向余弦和图像的第一列像素。 理解方向余弦不会伤害(参见http://mathworld.wolfram.com/DirectionCosine.html ),但dclunie建议的方法直接与它们一起工作,所以现在让我们说,他们给你的空间方向图像平面。 我标记他们自动对焦,使公式更容易。

现在,在dclunie给出的代码中(我相信它的目的是C,但它非常简单,它应该和Java,C#,awk,Vala,Octave等一样好),约定如下:

scr_ * =指的是soruce图像,即CT切片

dst_ * =指目标图像,即侦察员

* _pos_x,* _pos_y,* _pos_z =上面的X0,Y0,Z0

* _row_dircos_x,* _row_dircos_y,* _row_dircos_z =上面的A,B,C

* _col_dircos_x,* _col_dircos_y,* _col_dircos_z =上面的D,E,F

设置正确的值后,只需应用这些值:

dst_nrm_dircos_x = dst_row_dircos_y * dst_col_dircos_z 
                   - dst_row_dircos_z * dst_col_dircos_y; 
dst_nrm_dircos_y = dst_row_dircos_z * dst_col_dircos_x 
                   - dst_row_dircos_x * dst_col_dircos_z; 
dst_nrm_dircos_z = dst_row_dircos_x * dst_col_dircos_y 
                   - dst_row_dircos_y * dst_col_dircos_x; 

src_pos_x -= dst_pos_x;
src_pos_y -= dst_pos_y;
src_pos_z -= dst_pos_z;

dst_pos_x = dst_row_dircos_x * src_pos_x
          + dst_row_dircos_y * src_pos_y
          + dst_row_dircos_z * src_pos_z;

dst_pos_y = dst_col_dircos_x * src_pos_x
          + dst_col_dircos_y * src_pos_y
          + dst_col_dircos_z * src_pos_z;

dst_pos_z = dst_nrm_dircos_x * src_pos_x
          + dst_nrm_dircos_y * src_pos_y
          + dst_nrm_dircos_z * src_pos_z;

或者,如果你有一些奇特的矩阵类,你可以建立这个矩阵并将它乘以你的点坐标。

    [ dst_row_dircos_x  dst_row_dircos_y  dst_row_dircos_z  -dst_pos_x ] 
M = [ dst_col_dircos_x  dst_col_dircos_y  dst_col_dircos_z  -dst_pos_y ]
    [ dst_nrm_dircos_x  dst_nrm_dircos_y  dst_nrm_dircos_z  -dst_pos_z ]
    [ 0                 0                 0                 1          ]

这将是这样的:

Scout_Point(x,y,z,1) = M * CT_Point(x,y,z,1)

说这一切,我们应该转换CT的哪些点在侦察员创建一条线? 此外,这个dclunie已经提出了一个通用的解决方案:

我的方法是投影源图像边界框的正方形(即连接切片的TLHC,TRHC,BRHC和BLHC的线)。

如果您投影CT切片的四个角点,您将有一条垂直于侦察线的CT切片线,以及非垂直切片时的梯形线。 现在,如果您的CT切片与坐标轴对齐(即ImageOrientationPatient = [1 \ 0 \ 0 \ 0 \ 1 \ 0]),则这四个点很平常。 您可以使用行数/列数和沿x / y方向的像素距离计算图像的宽度/高度,并将其适当地相加。 如果你想实现一般情况,那么你需要一个小三角...或者可能不是。 如果你还没有阅读方向余弦的定义,那也许是时候了。

我会尽力让你走上正轨。 例如,在TRHC上工作时,您知道像素在图像平面中的位置:

# Pixel location of the TRHC
x_pixel = number_of_columns-1 # Counting from 0
y_pixel = 0
z_pixel = 0 # We're on a plane!

DICOM中的像素距离值被称为图像平面,因此您可以简单地将x和y乘以这些值,使其位置以毫米为单位,而z为0(像素和毫米)。 我正在谈论这些价值观:

(0028,0011) US 512                       #   2, 1 Columns
(0028,0010) US 512                       #   2, 1 Rows
(0028,0030) DS [0.9765625\0.9765625]     #  20, 2 PixelSpacing

上面的矩阵M是从全局到图像坐标的一般变换,具有可用的方向余弦。 你现在需要的是反作业(图像到全局)和源图像(CT切片)。 我会让你去挖掘几何图书,但我认为它应该是这样的(旋转部分被转置,翻译没有符号变化,当然我们使用src_ *值):

     [src_row_dircos_x  src_col_dircos_x  src_nrm_dircos_x  src_pos_x ]
M2 = [src_row_dircos_y  src_col_dircos_y  src_nrm_dircos_y  src_pos_y ]
     [src_row_dircos_z  src_col_dircos_z  src_nrm_dircos_z  src_pos_z ]
     [0                 0                 0                 1         ]

将CT切片中的点(例如四个角)转换为毫米,然后应用M2将它们放在全局坐标中。 然后,您可以将它们提供给dclunie报告的过程。 在使用它之前交叉检查我的数学,例如用于患者诊断! ;-)

希望这有助于理解更好的dclunie的方法。 干杯


David Brabant put you already in the right direction (if you want to work with DICOM you should definitely read and treasure dclunie's medical image FAQ). Let's see if I can elaborate on it and make it easier for you to implement.

I assume you have a tool/library to extract tags from a DICOM file (Offis' DCMTK?). For the sake of exemplification I'll refer to a CT scan (many slices, i.e. many images) and a scout image, onto which you want to display localizer lines. Each DICOM image, including your CT slices and your scout, contain full information about their location in space, in these two tags:

Group,Elem  VR Value                           Name of the tag   
---------------------------------------------------------------------
(0020,0032) DS [-249.51172\-417.51172\-821]  # ImagePositionPatient
                X0         Y0         Z0

(0020,0037) DS [1\0\0\0\1\0]                 # ImageOrientationPatient
                A B C D E F

ImagePositionPatient has the global coordinates in mm of the first pixel transmitted (the top left-hand corner pixel, to be clear) expressed as (x,y,z). I marked them X0, Y0, Z0. ImageOrientationPatient contains two vectors, both of three components, specifying the direction cosines of the first row of pixels and first column of pixels of the image. Understanding direction cosines doesn't hurt (see e.g. http://mathworld.wolfram.com/DirectionCosine.html), but the method suggested by dclunie works directly with them, so for now let's just say they give you the orientation in space of the image plane. I marked them A-F to make formulas easier.

Now, in the code given by dclunie (I believe it's intended to be C, but it's so simple it should work as well as Java, C#, awk, Vala, Octave, etc.) the conventions are the following:

scr_* = refers to the soruce image, i.e. the CT slice

dst_* = refers to the destination image, i.e. the scout

*_pos_x, *_pos_y, *_pos_z = the X0, Y0, Z0 above

*_row_dircos_x, *_row_dircos_y, *_row_dircos_z = the A, B, C above

*_col_dircos_x, *_col_dircos_y, *_col_dircos_z = the D, E, F above

After setting the right values just apply these:

dst_nrm_dircos_x = dst_row_dircos_y * dst_col_dircos_z 
                   - dst_row_dircos_z * dst_col_dircos_y; 
dst_nrm_dircos_y = dst_row_dircos_z * dst_col_dircos_x 
                   - dst_row_dircos_x * dst_col_dircos_z; 
dst_nrm_dircos_z = dst_row_dircos_x * dst_col_dircos_y 
                   - dst_row_dircos_y * dst_col_dircos_x; 

src_pos_x -= dst_pos_x;
src_pos_y -= dst_pos_y;
src_pos_z -= dst_pos_z;

dst_pos_x = dst_row_dircos_x * src_pos_x
          + dst_row_dircos_y * src_pos_y
          + dst_row_dircos_z * src_pos_z;

dst_pos_y = dst_col_dircos_x * src_pos_x
          + dst_col_dircos_y * src_pos_y
          + dst_col_dircos_z * src_pos_z;

dst_pos_z = dst_nrm_dircos_x * src_pos_x
          + dst_nrm_dircos_y * src_pos_y
          + dst_nrm_dircos_z * src_pos_z;

Or, if you have some fancy matrix class, you can build this matrix and multiply it with your point coordinates.

    [ dst_row_dircos_x  dst_row_dircos_y  dst_row_dircos_z  -dst_pos_x ] 
M = [ dst_col_dircos_x  dst_col_dircos_y  dst_col_dircos_z  -dst_pos_y ]
    [ dst_nrm_dircos_x  dst_nrm_dircos_y  dst_nrm_dircos_z  -dst_pos_z ]
    [ 0                 0                 0                 1          ]

That would be like this:

Scout_Point(x,y,z,1) = M * CT_Point(x,y,z,1)

Said all that, which points of the CT should we convert to create a line on the scout? Also for this dclunie already suggests a general solution:

"My approach is to project the square that is the bounding box of the source image (i.e. lines joining the TLHC, TRHC,BRHC and BLHC of the slice)."

If you project the four corner points of the CT slice, you'll have a line for CT slices perpendicular to the scout, and a trapezoid in case of non perpendicular slices. Now, if your CT slice is aligned with the coordinate axes (i.e. ImageOrientationPatient = [1\0\0\0\1\0]), the four points are trivial. You compute the width/height of the image in mm using the number of rows/columns and the pixel distance along x/y direction and sum things up appropriately. If you want to implement the generic case, then you need a little trigonometry... or maybe not. It's maybe time you read the definition of the direction cosines if you haven't yet.

I'll try to put you on track. E.g. working on the TRHC, you know where the voxel is in the image plane:

# Pixel location of the TRHC
x_pixel = number_of_columns-1 # Counting from 0
y_pixel = 0
z_pixel = 0 # We're on a plane!

The pixel distance values in DICOM are referred to the image plane, so you can simply multiply x and y by those values to have their position in mm, while z is 0 (both pixels and mm). I am talking about these values:

(0028,0011) US 512                       #   2, 1 Columns
(0028,0010) US 512                       #   2, 1 Rows
(0028,0030) DS [0.9765625\0.9765625]     #  20, 2 PixelSpacing

The matrix M above, is a generic transformation from global to image coordinates, having the direction cosines available. What you need now is something that does the inverse job (image to global) and on the source images (the CT slices). I'll let you go and dig in the geometry books to be sure, but I think it should be something like this (the rotation part is transposed, translation has no sign change and of course we use the src_* values):

     [src_row_dircos_x  src_col_dircos_x  src_nrm_dircos_x  src_pos_x ]
M2 = [src_row_dircos_y  src_col_dircos_y  src_nrm_dircos_y  src_pos_y ]
     [src_row_dircos_z  src_col_dircos_z  src_nrm_dircos_z  src_pos_z ]
     [0                 0                 0                 1         ]

Convert points in the CT slice (e.g. the four corners) to millimeters and then apply M2 to have them in global coordinates. Then you can feed them to the procedure reported by dclunie. Cross-check my maths before using it e.g. for patient diagnostics! ;-)

Hope this helps understanding better dclunie's method. Cheers

相关问答

更多
  • 如果您正在处理单色图像,则可以如下设置最小像素值与最大像素值之间的线性缩放比例: img = dicomread('filename'); imshow(img, [minAllowedPixValue maxAllowedPixValue]); 或者,您可以在全动态范围内显示图像: imshow(img, []); If you are dealing with monochrome images, you can set a linear scaling between a minimum and ...
  • 正如你所提到的,Alon在他的评论中提到,DICOM文件格式支持单帧和多帧像素数据。 “Cine”DICOM文件(通常是超声波文件)只是一个多帧DICOM文件。 像素数据的格式(单帧与多帧)由DICOM文件正在实现的服务对象对(SOP)类约束。 然后可以用不同的未压缩和压缩传输语法对DICOM文件进行编码。 对于压缩传输语法,DICOM定义了允许单帧和多帧像素数据的编码。 支持的传输语法包括标准和无损Jpeg,Jpeg-LS,Jpeg 2000和MPEG。 请注意,MPEG格式用于编码视频,这在技术上被编码 ...
  • 您最好的选择很可能是OFFIS DCMTK DICOM工具包,可在此处获得 。 这可能是最全面的开源DICOM工具包,它是用C / C ++编写的。 API文档可以在这里找到。 编辑有关传输语法转换的最相关的库可能是dcmjpeg和dcmjpls 。 在这些库中的各种应用程序的文档中,至少会列出与转换相关的传输语法。 支持的/已知的传输语法也在dcmdata / dcxfer.h包含文件中列举。 编辑2当涉及到开源C#DICOM工具包时, mdcm及其后续版本的fo-dicom是非常好的选择。 这两个工具包 ...
  • 如果可能,最好使用一些现有的库,例如MergeCom(非免费)或DCMTK。 它们处理各种条件,如显式VR,隐式VR,嵌套序列项的解析等。请查看有关dicom文件基本结构的链接: 简介DICOM单文件格式 。 要编辑DICOM文件,请记住您也可能更新了组长度标记。 此外,如果您想要验证编辑的值,那将会非常棘手,因为有太多的VR和不同的IOD具有不同的强制和可选标签。 所以我建议如果可能的话再次使用现有的库。 If possible, it is better to use some already exis ...
  • 大卫布拉班特让你已经朝着正确的方向发展(如果你想与DICOM合作,你一定要阅读并珍惜dclunie的医学影像常见问题 )。 让我们看看我是否可以详细阐述它,并使其更容易实施。 我假设你有一个工具/库来从DICOM文件中提取标签(Offis'DCMTK?)。 为了举例说明,我将参考CT扫描(许多切片,即许多图像)和一个侦察图像,您要在其上显示定位线。 每个DICOM图像(包括您的CT片和您的侦察器)都包含有关它们在太空中的位置的完整信息,在这两个标签中: Group,Elem VR Value ...
  • 这是一种方法: string filename = "output.dcm"; DicomDataset ds = new DicomDataset(); //Main dataset ds.Add(DicomTag.SpecificCharacterSet, "ISO_IR 100"); //Add some items ds.Add(DicomTag.PatientID, "191212121212"); DicomDataset sqContent = new DicomDataset(); // ...
  • 有几个类似的问题与使用ClearCanvas渲染图像有关。 请查看此问题和此问题的答案。 There has been several questions similar to this related to rendering images with ClearCanvas. Please see the answer for this question and this question.
  • 您查找标记的方式仅在DICOM标记树的最外层次结构中查找。 要正确搜索标记,您需要先访问正确的序列,然后再访问相应的项目,然后搜索该项目中的标记。 DICOM数据集可能包含可以进一步嵌套的序列(由VR SQ标识)。 从这里复制以下内容: 标识为“SQ”的VR应用于具有由零个或多个项目的序列组成的值的数据元素,其中每个项目包含一组数据元素。 SQ提供了一种灵活的编码方案,可用于重复数据元素集的简单结构,或者通常称为文件夹的更复杂信息对象定义的编码。 SQ数据元素也可以递归使用,以包含多级嵌套结构。 SQ数据元 ...
  • 对于被认为代表相同对象的任何两个图像A和B ,配准是识别A中的每个像素/界标B中的等效像素/界标的动作。 假设A和B中的每个像素都可以嵌入坐标系中,则配准通常需要变换 A ,使得在变换之后 , A中每个像素的坐标与B中的等效像素的坐标一致(即,目标是两个对象在该坐标空间中重叠) 等距变换是指应用变换后A中任意两个像素之间的距离与B中等效的两个像素之间的距离不变的等变换。 例如,空间旋转,反射(即镜像)和平移(即将物体沿特定方向移动)都是等距变换。 仅应用等距变换的配准算法被认为是刚性的 。 仿射变换类似于等 ...
  • 我认为答案可以在以下方面找到: ftp://medical.nema.org/medical/dicom/final/sup120_ft.pdf 标记0070,0282“复合图形单位”是枚举值,可以是“PIXEL”或“DISPLAY” 如果它是“PIXEL”,则您的坐标似乎必须在0 \ 0到Columns \ Rows的范围内。 (引自标签描述)。 如果是“DISPLAY”,则值必须在0.0到1.0的范围内,并且它们是“显示区域”的分数 显示区域是一个单独的IOD,您可以在第1200页左右找到 http:/ ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。